This report contains a summary of cell type annotation results for library SCPCL000040. The goal of this report is to provide more detailed information about cell type annotation results as an initial evaluation of their quality and reliability.

Performing cell type annotation is an inherently challenging task with high levels of uncertainty, especially when using automated annotation methods. One way to address this is to use multiple cell type annotation approaches and compare the results, as we have begun to do in this report.

When multiple methods annotate a given cell as the same or similar cell type, this may qualitatively indicate a more robust annotation.

Note that the contents of this report will vary based on which cell type annotations are present. Further, be aware that different cell type annotation methods may assign different labels to the same or similar cell type (e.g., the different string representations B cell naive and Naive B cell), due to use of different underlying reference datasets. Please note that all cell type annotation reference datasets are derived from normal (not tumor) tissue.

This library contains the following cell type annotations:

  • Annotations from SingleR, a reference-based approach (Looney et al. 2019). The BlueprintEncodeData dataset, obtained from the celldex package, was used for reference annotations.
  • Annotations from CellAssign, a marker-gene-based approach (Zhang et al. 2019). Marker genes for cell types were obtained from PanglaoDB and compiled into a reference named brain-compartment. This reference includes the following organs and tissue compartments: brain, embryo, immune system, and vasculature.

Sample metadata

The below table summarizes clinical metadata for the sample associated with this library. Blue hyperlinks are present for any terms with an ontology term identifier associated with the displayed human readable value. These links will direct you to a web page with information about that ontology term identifier.

Sample ID SCPCS000040
Diagnosis Pilocytic astrocytoma
Subdiagnosis NA
Tissue location Thalamic
Disease timing Initial diagnosis
Age 11
Sex F
Organism Homo sapiens
Sample type patient tissue

Cell type Annotation Summary

The plots and tables included here detail the results from performing cell type annotation.

Statistics

SingleR cell type annotations

In this table, cells labeled “Unknown cell type” are those which SingleR pruned due to low-quality assignments. In the processed result files, these cells are labeled NA.
Annotated cell type Number of cells Percent of cells
CD4-positive, alpha-beta T cell 1551 26.4%
central memory CD8-positive, alpha-beta T cell 972 16.55%
common lymphoid progenitor 540 9.19%
central memory CD4-positive, alpha-beta T cell 536 9.12%
regulatory T cell 486 8.27%
effector memory CD8-positive, alpha-beta T cell 370 6.3%
dendritic cell 250 4.26%
CD8-positive, alpha-beta T cell 203 3.46%
plasma cell 161 2.74%
natural killer cell 157 2.67%
effector memory CD4-positive, alpha-beta T cell 156 2.66%
megakaryocyte-erythroid progenitor cell 120 2.04%
granulocyte monocyte progenitor cell 102 1.74%
hematopoietic stem cell 91 1.55%
hematopoietic multipotent progenitor cell 62 1.06%
erythrocyte 44 0.75%
neuron 29 0.49%
megakaryocyte 7 0.12%
class switched memory B cell 6 0.1%
keratinocyte 6 0.1%
melanocyte 5 0.09%
memory B cell 3 0.05%
naive B cell 3 0.05%
epithelial cell 2 0.03%
inflammatory macrophage 2 0.03%
microvascular endothelial cell 2 0.03%
monocyte 2 0.03%
common myeloid progenitor 1 0.02%
fat cell 1 0.02%
macrophage 1 0.02%
Unknown cell type 3 0.05%

CellAssign cell type annotations

In this table, cells labeled “Unknown cell type” are those which CellAssign could not confidently assign to a label in the reference list. In the processed result files, these cells are labeled "other".
Annotated cell type Number of cells Percent of cells
T helper cells 56 0.95%
T cells 42 0.72%
Nuocytes 12 0.2%
Microglia 9 0.15%
T regulatory cells 9 0.15%
Oligodendrocyte progenitor cells 6 0.1%
Monocytes 2 0.03%
Dendritic cells 1 0.02%
Endothelial cells (aorta) 1 0.02%
GABAergic neurons 1 0.02%
Gamma delta T cells 1 0.02%
Macrophages 1 0.02%
Myeloid-derived suppressor cells 1 0.02%
Natural killer T cells 1 0.02%
Neural stem/precursor cells 1 0.02%
NK cells 1 0.02%
Trophoblast cells 1 0.02%
Unknown cell type 5728 97.51%

UMAPs

In this section, we show UMAPs colored by clusters. Clusters were calculated using the graph-based Louvain algorithm with Jaccard weighting.

Next, we show UMAPs colored by cell types. For each cell typing method, we show a separate faceted UMAP. In each panel, cells that were assigned the given cell type label are colored, while all other cells are in grey.

For legibility, only the seven most common cell types are shown. All other cell types are grouped together and labeled “All remaining cell types” (not to be confused with “Unknown cell type” which represents cells that could not be classified).

Cell label comparison plots

This section displays heatmaps comparing cell labels from various methods.

We use the Jaccard similarity index to display the agreement between between pairs of labels assigned by different annotation methods.

The Jaccard index reflects the degree of overlap between the two labels and ranges from 0 to 1.

  • If the labels are assigned to identical sets of cells, the Jaccard index will be 1.
  • If the labels are assigned to completely non-overlapping sets of cells, the Jaccard index will be 0.

High agreement between methods qualitatively indicates higher confidence in the cell type annotation.

Unsupervised clustering

Here we show the labels from unsupervised clustering compared to cell type annotations. Cluster assignment was performed using the Louvain algorithm.

Automated annotations

This section displays a heatmap directly comparing SingleR and CellAssign cell type annotations. Note that due to different annotations references, these methods may use different names for similar cell types.

Quality assessments of automated annotations

SingleR annotations

To assess the quality of SingleR cell type annotations, we use the delta median statistic.

  • Delta median is calculated for each cell as the difference between the SingleR score of the annotated cell type label and the median score of the other cell type labels in the reference dataset.
  • Higher delta median values indicate higher quality cell type annotations.

You can interpret this plot as follows:

  • Each point represents the delta median statistic of a given cell whose SingleR annotation is shown on the y-axis.
  • The point style indicates SingleR’s quality assessment of the annotation:
    • High-quality cell annotations are shown as closed points.
    • Low-quality cell annotations are shown as open points. In other sections of this report, these cells are labeled as Unknown cell types.
    • For more information on how SingleR calculates annotation quality, please refer to this SingleR documentation.
  • Diamonds represent the median of the delta median statistic specifically among high-quality annotations for the given cell type annotation.

CellAssign annotations

To assess the quality of CellAssign cell type annotations, we consider the probability associated with the annotated cell type. These probabilities are provided directly by CellAssign:

  • CellAssign first calculates the probability of each cell being annotated as each cell type present in the reference.
  • CellAssign then annotates cells by selecting the cell type with the highest probability among all cell types considered.
  • These probabilities range from 0 to 1, with larger values indicating greater confidence in a given cell type label. We therefore expect reliable labels to have values close to 1.

The plot below shows the distribution of CellAssign-calculated probabilities for the final cell type labels. Line segments represent individual values that comprise each distribution.

For cell types with 2 or fewer labeled cells, only the individual value line segments are shown. Line segments are also taller for any cell type label with 5 or fewer cells.

Session Info

R session information

## ─ Session info ───────────────────────────────────────────────────────────────
##  setting  value
##  version  R version 4.4.1 (2024-06-14)
##  os       Ubuntu 22.04.4 LTS
##  system   x86_64, linux-gnu
##  ui       X11
##  language (EN)
##  collate  en_US.UTF-8
##  ctype    en_US.UTF-8
##  tz       Etc/UTC
##  date     2024-08-02
##  pandoc   2.9.2.1 @ /usr/bin/ (via rmarkdown)
## 
## ─ Packages ───────────────────────────────────────────────────────────────────
##  package              * version  date (UTC) lib source
##  abind                  1.4-5    2016-07-21 [1] RSPM (R 4.4.0)
##  beachmat               2.20.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  beeswarm               0.4.0    2021-06-01 [1] RSPM (R 4.4.0)
##  Biobase              * 2.64.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  BiocGenerics         * 0.50.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  BiocNeighbors          1.22.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  BiocParallel           1.38.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  BiocSingular           1.20.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  bluster                1.14.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  bslib                  0.7.0    2024-03-29 [1] RSPM (R 4.4.0)
##  cachem                 1.1.0    2024-05-16 [1] RSPM (R 4.4.0)
##  Cairo                  1.6-2    2023-11-28 [1] RSPM (R 4.4.0)
##  circlize               0.4.16   2024-02-20 [1] RSPM (R 4.4.0)
##  cli                    3.6.3    2024-06-21 [1] RSPM (R 4.4.0)
##  clue                   0.3-65   2023-09-23 [1] RSPM (R 4.4.0)
##  cluster                2.1.6    2023-12-01 [2] CRAN (R 4.4.1)
##  codetools              0.2-20   2024-03-31 [2] CRAN (R 4.4.1)
##  colorspace             2.1-0    2023-01-23 [1] RSPM (R 4.4.0)
##  ComplexHeatmap         2.20.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  crayon                 1.5.3    2024-06-20 [1] RSPM (R 4.4.0)
##  DelayedArray           0.30.1   2024-05-07 [1] Bioconductor 3.19 (R 4.4.1)
##  DelayedMatrixStats     1.26.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  digest                 0.6.36   2024-06-23 [1] RSPM (R 4.4.0)
##  doParallel             1.0.17   2022-02-07 [1] RSPM (R 4.4.0)
##  dplyr                * 1.1.4    2023-11-17 [1] RSPM (R 4.4.0)
##  dqrng                  0.4.1    2024-05-28 [1] RSPM (R 4.4.0)
##  edgeR                  4.2.0    2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  evaluate               0.24.0   2024-06-10 [1] RSPM (R 4.4.0)
##  fansi                  1.0.6    2023-12-08 [1] RSPM (R 4.4.0)
##  farver                 2.1.2    2024-05-13 [1] RSPM (R 4.4.0)
##  fastmap                1.2.0    2024-05-15 [1] RSPM (R 4.4.0)
##  flexmix                2.3-19   2023-03-16 [1] RSPM (R 4.4.0)
##  forcats                1.0.0    2023-01-29 [1] RSPM (R 4.4.0)
##  foreach                1.5.2    2022-02-02 [1] RSPM (R 4.4.0)
##  generics               0.1.3    2022-07-05 [1] RSPM (R 4.4.0)
##  GenomeInfoDb         * 1.40.1   2024-05-24 [1] Bioconductor 3.19 (R 4.4.1)
##  GenomeInfoDbData       1.2.12   2024-06-25 [1] Bioconductor
##  GenomicRanges        * 1.56.1   2024-06-12 [1] Bioconductor 3.19 (R 4.4.1)
##  getopt                 1.20.4   2023-10-01 [1] RSPM (R 4.4.0)
##  GetoptLong             1.0.5    2020-12-15 [1] RSPM (R 4.4.0)
##  ggbeeswarm             0.7.2    2023-04-29 [1] RSPM (R 4.4.0)
##  ggforce                0.4.2    2024-02-19 [1] RSPM (R 4.4.0)
##  ggplot2              * 3.5.1    2024-04-23 [1] RSPM (R 4.4.0)
##  ggrepel                0.9.5    2024-01-10 [1] RSPM (R 4.4.0)
##  GlobalOptions          0.1.2    2020-06-10 [1] RSPM (R 4.4.0)
##  glue                   1.7.0    2024-01-09 [1] RSPM (R 4.4.0)
##  gridExtra              2.3      2017-09-09 [1] RSPM (R 4.4.0)
##  gtable                 0.3.5    2024-04-22 [1] RSPM (R 4.4.0)
##  highr                  0.11     2024-05-26 [1] RSPM (R 4.4.0)
##  hms                    1.1.3    2023-03-21 [1] RSPM (R 4.4.0)
##  htmltools              0.5.8.1  2024-04-04 [1] RSPM (R 4.4.0)
##  httr                   1.4.7    2023-08-15 [1] RSPM (R 4.4.0)
##  igraph                 2.0.3    2024-03-13 [1] RSPM (R 4.4.0)
##  IRanges              * 2.38.1   2024-07-03 [1] Bioconductor 3.19 (R 4.4.1)
##  irlba                  2.3.5.1  2022-10-03 [1] RSPM (R 4.4.0)
##  iterators              1.0.14   2022-02-05 [1] RSPM (R 4.4.0)
##  jquerylib              0.1.4    2021-04-26 [1] RSPM (R 4.4.0)
##  jsonlite               1.8.8    2023-12-04 [1] RSPM (R 4.4.0)
##  kableExtra             1.4.0    2024-01-24 [1] RSPM (R 4.4.0)
##  knitr                  1.48     2024-07-07 [1] RSPM (R 4.4.0)
##  labeling               0.4.3    2023-08-29 [1] RSPM (R 4.4.0)
##  lattice                0.22-6   2024-03-20 [2] CRAN (R 4.4.1)
##  lifecycle              1.0.4    2023-11-07 [1] RSPM (R 4.4.0)
##  limma                  3.60.3   2024-06-16 [1] Bioconductor 3.19 (R 4.4.1)
##  locfit                 1.5-9.10 2024-06-24 [1] RSPM (R 4.4.0)
##  lubridate              1.9.3    2023-09-27 [1] RSPM (R 4.4.0)
##  magrittr               2.0.3    2022-03-30 [1] RSPM (R 4.4.0)
##  MASS                   7.3-60.2 2024-04-26 [1] RSPM (R 4.4.1)
##  Matrix                 1.7-0    2024-04-26 [2] CRAN (R 4.4.1)
##  MatrixGenerics       * 1.16.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  matrixStats          * 1.3.0    2024-04-11 [1] RSPM (R 4.4.0)
##  metapod                1.12.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  miQC                   1.12.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  modeltools             0.2-23   2020-03-05 [1] RSPM (R 4.4.0)
##  munsell                0.5.1    2024-04-01 [1] RSPM (R 4.4.0)
##  nnet                   7.3-19   2023-05-03 [2] CRAN (R 4.4.1)
##  optparse             * 1.7.5    2024-04-16 [1] RSPM (R 4.4.0)
##  pillar                 1.9.0    2023-03-22 [1] RSPM (R 4.4.0)
##  pkgconfig              2.0.3    2019-09-22 [1] RSPM (R 4.4.0)
##  png                    0.1-8    2022-11-29 [1] RSPM (R 4.4.0)
##  polyclip               1.10-6   2023-09-27 [1] RSPM (R 4.4.0)
##  purrr                  1.0.2    2023-08-10 [1] RSPM (R 4.4.0)
##  R6                     2.5.1    2021-08-19 [1] RSPM (R 4.4.0)
##  RColorBrewer           1.1-3    2022-04-03 [1] RSPM (R 4.4.0)
##  Rcpp                   1.0.12   2024-01-09 [1] RSPM (R 4.4.0)
##  readr                  2.1.5    2024-01-10 [1] RSPM (R 4.4.0)
##  rjson                  0.2.21   2022-01-09 [1] RSPM (R 4.4.0)
##  rlang                  1.1.4    2024-06-04 [1] RSPM (R 4.4.0)
##  rmarkdown              2.27     2024-05-17 [1] RSPM (R 4.4.0)
##  rstudioapi             0.16.0   2024-03-24 [1] RSPM (R 4.4.0)
##  rsvd                   1.0.5    2021-04-16 [1] RSPM (R 4.4.0)
##  S4Arrays               1.4.1    2024-05-20 [1] Bioconductor 3.19 (R 4.4.1)
##  S4Vectors            * 0.42.1   2024-07-03 [1] Bioconductor 3.19 (R 4.4.1)
##  sass                   0.4.9    2024-03-15 [1] RSPM (R 4.4.0)
##  ScaledMatrix           1.12.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  scales                 1.3.0    2023-11-28 [1] RSPM (R 4.4.0)
##  scater                 1.32.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  scpcaTools             0.4.0    2024-07-08 [1] local
##  scran                  1.32.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  scuttle                1.14.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  sessioninfo            1.2.2    2021-12-06 [1] RSPM (R 4.4.0)
##  shape                  1.4.6.1  2024-02-23 [1] RSPM (R 4.4.0)
##  SingleCellExperiment * 1.26.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  SparseArray            1.4.8    2024-05-24 [1] Bioconductor 3.19 (R 4.4.1)
##  sparseMatrixStats      1.16.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  statmod                1.5.0    2023-01-06 [1] RSPM (R 4.4.0)
##  stringi                1.8.4    2024-05-06 [1] RSPM (R 4.4.0)
##  stringr                1.5.1    2023-11-14 [1] RSPM (R 4.4.0)
##  SummarizedExperiment * 1.34.0   2024-05-01 [1] Bioconductor 3.19 (R 4.4.1)
##  svglite                2.1.3    2023-12-08 [1] RSPM (R 4.4.0)
##  systemfonts            1.1.0    2024-05-15 [1] RSPM (R 4.4.0)
##  tibble                 3.2.1    2023-03-20 [1] RSPM (R 4.4.0)
##  tidyr                  1.3.1    2024-01-24 [1] RSPM (R 4.4.0)
##  tidyselect             1.2.1    2024-03-11 [1] RSPM (R 4.4.0)
##  timechange             0.3.0    2024-01-18 [1] RSPM (R 4.4.0)
##  tweenr                 2.0.3    2024-02-26 [1] RSPM (R 4.4.0)
##  tzdb                   0.4.0    2023-05-12 [1] RSPM (R 4.4.0)
##  UCSC.utils             1.0.0    2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  utf8                   1.2.4    2023-10-22 [1] RSPM (R 4.4.0)
##  vctrs                  0.6.5    2023-12-01 [1] RSPM (R 4.4.0)
##  vipor                  0.4.7    2023-12-18 [1] RSPM (R 4.4.0)
##  viridis                0.6.5    2024-01-29 [1] RSPM (R 4.4.0)
##  viridisLite            0.4.2    2023-05-02 [1] RSPM (R 4.4.0)
##  withr                  3.0.0    2024-01-16 [1] RSPM (R 4.4.0)
##  xfun                   0.45     2024-06-16 [1] RSPM (R 4.4.0)
##  xml2                   1.3.6    2023-12-04 [1] RSPM (R 4.4.0)
##  XVector                0.44.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
##  yaml                   2.3.9    2024-07-05 [1] RSPM (R 4.4.0)
##  zlibbioc               1.50.0   2024-04-30 [1] Bioconductor 3.19 (R 4.4.1)
## 
##  [1] /usr/local/lib/R/site-library
##  [2] /usr/local/lib/R/library
## 
## ──────────────────────────────────────────────────────────────────────────────
LS0tCnBhcmFtczoKICBsaWJyYXJ5OiBFeGFtcGxlCiAgcHJvY2Vzc2VkX3NjZTogTlVMTAogIGRhdGU6ICFyIFN5cy5EYXRlKCkKdGl0bGU6ICJgciBnbHVlOjpnbHVlKCdTY1BDQSBTdXBwbGVtZW50YWwgY2VsbCB0eXBlIHJlcG9ydCBmb3Ige3BhcmFtcyRsaWJyYXJ5fScpYCIKYXV0aG9yOiAiQ2hpbGRob29kIENhbmNlciBEYXRhIExhYiIKZGF0ZTogImByIHBhcmFtcyRkYXRlYCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19kZXB0aDogMgogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCi0tLQoKYGBge3Igc2V0dXAsIG1lc3NhZ2UgPSBGQUxTRSwgZWNobyA9IEZBTFNFfQojIGtuaXRyIG9wdGlvbnMKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBGQUxTRQopCgpsaWJyYXJ5KFNpbmdsZUNlbGxFeHBlcmltZW50KQpsaWJyYXJ5KGdncGxvdDIpCgojIFNldCBkZWZhdWx0IGdncGxvdCB0aGVtZQp0aGVtZV9zZXQoCiAgdGhlbWVfYncoKSArCiAgICB0aGVtZSgKICAgICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4ocmVwKDIwLCA0KSksCiAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ0cmFuc3BhcmVudCIpCiAgICApCikKCiMgVGhpcyBfaXNfIHRoZSBzdXBwbGVtZW50YWwgcmVwb3J0CiMgd2Ugc2hvdWxkIG5vdCBwcmludCB0aGUgY2h1bmsgZnJvbSBjZWxsdHlwZXNfcWMucm1kIHJlY2FwaXR1bGF0aW5nIGJ1bGxldHMKIyAgYW5kIHBvaW50aW5nIHVzZXJzIHRvIHRoaXMgc3VwcCByZXBvcnQKaXNfc3VwcGxlbWVudGFsIDwtIFRSVUUKYGBgCgo8IS0tIEltcG9ydCBzaGFyZWQgZnVuY3Rpb25zIGZvciBjZWxsIHR5cGUgd3JhbmdsaW5nIC0tPgpgYGB7ciwgY2hpbGQ9J3V0aWxzL2NlbGx0eXBlX2Z1bmN0aW9ucy5ybWQnfQpgYGAKYGBge3IsIGNoaWxkPSd1dGlscy9yZXBvcnRfZnVuY3Rpb25zLnJtZCd9CmBgYAoKCjwhLS0gRGVmaW5lIGhlbHBlciBmdW5jdGlvbnMgZm9yIGNhbGN1bGF0aW5nIEphY2NhcmQgbWF0cmljZXMgLS0+CmBgYHtyfQojJyBGdW5jdGlvbiB0byBjYWxjdWxhdGUgSmFjY2FyZCBzaW1pbGFyaXR5IG9uIHR3byB2ZWN0b3JzCiMnCiMnIEBwYXJhbSB2ZWMxIEZpcnN0IHZlY3RvcgojJyBAcGFyYW0gdmVjMiBTZWNvbmQgdmVjdG9yCiMnCiMnIEByZXR1cm4gSmFjY2FyZCBzaW1pbGFyaXR5IGJldHdlZW4gdGhlIHZlY3RvcnMKamFjY2FyZCA8LSBmdW5jdGlvbih2ZWMxLCB2ZWMyKSB7CiAgbGVuZ3RoKGludGVyc2VjdCh2ZWMxLCB2ZWMyKSkgLyBsZW5ndGgodW5pb24odmVjMSwgdmVjMikpCn0KCgojIFdyYXBwZXIgZnVuY3Rpb24gdG8gY2FsY3VsYXRlIGphY2NhcmQgc2ltaWxhcml0eSBtYXRyaXggZm9yIHR3byBjYXRlZ29yaWNhbCB2YXJpYWJsZXMKIycKIycgQHBhcmFtIGNlbGx0eXBlX2RmIFRoZSBjZWxsdHlwZV9kZiBkYXRhIGZyYW1lIHdoaWNoIG11c3QgY29udGFpbiB0aGVzZSBjb2x1bW5zOgojJyAgIGBjb2xuYW1lMWAsIGBjb2xuYW1lMmAsIGFuZCBgYmFyY29kZXNgCiMnIEBwYXJhbSBjb2xuYW1lMSBDb2x1bW4gbmFtZSwgYXMgYSBzdHJpbmcsIG9mIGZpcnN0IGNhdGVnb3JpY2FsIHZhcmlhYmxlIG9mIGludGVyZXN0CiMnIEBwYXJhbSBjb2xuYW1lMiBDb2x1bW4gbmFtZSwgYXMgYSBzdHJpbmcsIG9mIHNlY29uZCBjYXRlZ29yaWNhbCB2YXJpYWJsZSBvZiBpbnRlcmVzdAojJwojJyBAcmV0dXJuIEphY2NhcmQgc2ltaWxhcml0eSBtYXRyaXggZm9yIHRoZSB0d28gY29sdW1ucy4gYGNvbG5hbWUxYCB2YWx1ZXMgd2lsbAojJyAgIGJlIHJvdyBuYW1lcyBhbmQgYGNvbG5hbWUyYCB2YWx1ZXMgd2lsbCBiZSBjb2x1bW4gbmFtZXMgaW4gdGhlIGZpbmFsIG1hdHJpeAptYWtlX2phY2NhcmRfbWF0cml4IDwtIGZ1bmN0aW9uKGNlbGx0eXBlX2RmLCBjb2xuYW1lMSwgY29sbmFtZTIpIHsKICAjIG1ha2UgbGlzdHMgb2YgYmFyY29kZXMgZm9yIGVhY2ggY2F0ZWdvcnksIG5hbWVkIGJ5IHRoZSBjYXRlZ29yeQogIGlkMV9saXN0IDwtIHNwbGl0KGNlbGx0eXBlX2RmJGJhcmNvZGVzLCBjZWxsdHlwZV9kZltbY29sbmFtZTFdXSkKICBpZDJfbGlzdCA8LSBzcGxpdChjZWxsdHlwZV9kZiRiYXJjb2RlcywgY2VsbHR5cGVfZGZbW2NvbG5hbWUyXV0pCgogICMgY3JlYXRlIHRoZSBncmlkIG9mIGNvbXBhcmlzb25zCiAgY3Jvc3NfZGYgPC0gdGlkeXI6OmV4cGFuZF9ncmlkKGlkMSA9IG5hbWVzKGlkMV9saXN0KSwgaWQyID0gbmFtZXMoaWQyX2xpc3QpKQoKICAjIGNhbGN1bGF0ZSBhIHNpbmdsZSBKYWNjYXJkIGluZGV4IGZvciBlYWNoIGNvbWJpbmF0aW9uIHVzaW5nIHNwbGl0IGxpc3RzICYgaWRzCiAgamFjY2FyZF9zY29yZXMgPC0gY3Jvc3NfZGYgfD4KICAgIHB1cnJyOjpwbWFwX2RibChcKGlkMSwgaWQyKXsKICAgICAgamFjY2FyZChpZDFfbGlzdFtbaWQxXV0sIGlkMl9saXN0W1tpZDJdXSkKICAgIH0pCgogICMgYWRkIHNjb3JlcyB0byB0aGUgY29tcGFyaXNvbiBncmlkIGFuZCBjb252ZXJ0IHRvIG1hdHJpeAogIGphY2NhcmRfbWF0cml4IDwtIGNyb3NzX2RmIHw+CiAgICBkcGx5cjo6bXV0YXRlKGphY2NhcmQgPSBqYWNjYXJkX3Njb3JlcykgfD4KICAgICMgY29udmVydCB0byBtYXRyaXgKICAgIHRpZHlyOjpwaXZvdF93aWRlcigKICAgICAgbmFtZXNfZnJvbSA9ICJpZDIiLAogICAgICB2YWx1ZXNfZnJvbSA9ICJqYWNjYXJkIgogICAgKSB8PgogICAgdGliYmxlOjpjb2x1bW5fdG9fcm93bmFtZXModmFyID0gImlkMSIpIHw+CiAgICBhcy5tYXRyaXgoKQoKICByZXR1cm4oamFjY2FyZF9tYXRyaXgpCn0KYGBgCgoKPCEtLSBEZWZpbmUgdmFyaWFibGVzLCBvcHRpb25zLCBhbmQgZnVuY3Rpb25zIGZvciBwbG90dGluZyBoZWF0bWFwcyAtLT4KYGBge3J9CiMgRGVmaW5lIGNvbG9yIHJhbXAgZm9yIHNoYXJlZCB1c2UgaW4gdGhlIGhlYXRtYXAKaGVhdG1hcF9jb2xfZnVuIDwtIGNpcmNsaXplOjpjb2xvclJhbXAyKGMoMCwgMSksIGNvbG9ycyA9IGMoIndoaXRlIiwgImRhcmtzbGF0ZWJsdWUiKSkKCiMgU2V0IGhlYXRtYXAgcGFkZGluZyBvcHRpb24KaGVhdG1hcF9wYWRkaW5nIDwtIDAuMgpDb21wbGV4SGVhdG1hcDo6aHRfb3B0KFRJVExFX1BBRERJTkcgPSBncmlkOjp1bml0KGhlYXRtYXBfcGFkZGluZywgImluIikpCgojJyBDcmVhdGUgYSBDb21wbGV4SGVhdG1hcCBmcm9tIGEgbWF0cml4CiMnCiMnIEBwYXJhbSBtYXQgTWF0cml4IHRvIGNyZWF0ZSBoZWF0bWFwIGZyb20uCiMnIEBwYXJhbSByb3dfdGl0bGUgTGFiZWwgZm9yIHJvdyB0aXRsZS4KIycgQHBhcmFtIGNvbHVtbl90aXRsZSBMYWJlbCBmb3IgY29sdW1uIHRpdGxlLgojJyBAcGFyYW0gbGFiZWxzX2ZvbnRfc2l6ZSBGb250IHNpemUgdG8gdXNlIGZvciByb3dzIGFuZCBjb2x1bW4gbGFiZWxzLgojJyBAcGFyYW0ga2VlcF9sZWdlbmRfbmFtZSBUaGUgbmFtZSB0byB1c2UgaW4gdGhlIGxlZ2VuZAojJyBAcGFyYW0gY29sX2Z1biBDb2xvciBmdW5jdGlvbiBmb3IgdGhlIGhlYXRtYXAgcGFsZXR0ZS4gRGVmYXVsdCBpcyBgaGVhdG1hcF9jb2xfZnVuYC4KIycgQHBhcmFtIC4uLiBBZGRpdGlvbmFsIGFyZ3VtZW50cyB0byBwYXNzIHRvIGBDb21wbGV4SGVhdG1hcDo6SGVhdG1hcCgpYAojJwojJyBAcmV0dXJuIEEgQ29tcGxleEhlYXRtYXAgb2JqZWN0CmNyZWF0ZV9zaW5nbGVfaGVhdG1hcCA8LSBmdW5jdGlvbigKICAgIG1hdCwKICAgIHJvd190aXRsZSwKICAgIGNvbHVtbl90aXRsZSwKICAgIGxhYmVsc19mb250X3NpemUsCiAgICBrZWVwX2xlZ2VuZF9uYW1lLAogICAgY29sX2Z1biA9IGhlYXRtYXBfY29sX2Z1biwKICAgIC4uLikgewogIGhlYXQgPC0gQ29tcGxleEhlYXRtYXA6OkhlYXRtYXAoCiAgICB0KG1hdCksICMgdHJhbnNwb3NlIGJlY2F1c2UgbWF0cml4IHJvd3MgYXJlIGluIGNvbW1vbiAmIHdlIHdhbnQgYSB2ZXJ0aWNhbCBhcnJhbmdlbWVudAogICAgY29sID0gY29sX2Z1biwKICAgIGJvcmRlciA9IFRSVUUsICMgZWFjaCBoZWF0bWFwIGdldHMgaXRzIG93biBvdXRsaW5lCiAgICAjIyBSb3cgcGFyYW1ldGVycwogICAgY2x1c3Rlcl9yb3dzID0gRkFMU0UsCiAgICByb3dfdGl0bGUgPSByb3dfdGl0bGUsICMgZWFjaCBoZWF0bWFwIGdldHMgaXRzIG93biB0aXRsZQogICAgcm93X3RpdGxlX2dwID0gZ3JpZDo6Z3Bhcihmb250c2l6ZSA9IDEwKSwKICAgIHJvd190aXRsZV9zaWRlID0gInJpZ2h0IiwKICAgIHJvd19uYW1lc19zaWRlID0gImxlZnQiLAogICAgcm93X25hbWVzX2dwID0gZ3JpZDo6Z3Bhcihmb250c2l6ZSA9IGxhYmVsc19mb250X3NpemUpLAogICAgIyMgQ29sdW1uIHBhcmFtZXRlcnMKICAgIGNsdXN0ZXJfY29sdW1ucyA9IEZBTFNFLAogICAgY29sdW1uX3RpdGxlID0gY29sdW1uX3RpdGxlLAogICAgY29sdW1uX3RpdGxlX2dwID0gZ3JpZDo6Z3Bhcihmb250c2l6ZSA9IDEwKSwKICAgIGNvbHVtbl9uYW1lc19zaWRlID0gImJvdHRvbSIsCiAgICBjb2x1bW5fbmFtZXNfZ3AgPSBncmlkOjpncGFyKGZvbnRzaXplID0gbGFiZWxzX2ZvbnRfc2l6ZSksCiAgICAjIyMgcGFzc2VkIGluIGFyZ3MKICAgIC4uLiwKICAgICMjIExlZ2VuZCBwYXJhbWV0ZXJzCiAgICBoZWF0bWFwX2xlZ2VuZF9wYXJhbSA9IGxpc3QoCiAgICAgIHRpdGxlID0gIkphY2NhcmQgaW5kZXgiLAogICAgICBkaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIsCiAgICAgIGxlZ2VuZF93aWR0aCA9IHVuaXQoMS41LCAiaW4iKQogICAgKSwKICAgICMgb25seSBrZWVwIGxlZ2VuZHMgdGhhdCBtYXRjaCBga2VlcF9sZWdlbmRfbmFtZWAKICAgIHNob3dfaGVhdG1hcF9sZWdlbmQgPSByb3dfdGl0bGUgPT0ga2VlcF9sZWdlbmRfbmFtZSwKICApCgogIHJldHVybihoZWF0KQp9CgojJyBGdW5jdGlvbiB0byBwbG90IGEgdmVydGljYWxseS1zdGFja2VkIENvbXBsZXhIZWF0bWFwIGZyb20gYSBsaXN0IG9mIG1hdHJpY2VzCiMnCiMnIEBwYXJhbSBtYXRyaXhfbGlzdCBMaXN0IG9mIG1hdHJpY2VzIHRvIHBsb3QgaW4gYSB2ZXJ0aWNhbCBsYXlvdXQKIycgQHBhcmFtIGNvbHVtbl90aXRsZSBUaXRsZSB0byB1c2UgZm9yIGNvbHVtbnMsIHNoYXJlZCBhbW9uZyBhbGwgaGVhdG1hcHMKIycgQHBhcmFtIGxhYmVsc19mb250X3NpemUgRm9udCBzaXplIHRvIHVzZSBmb3Igcm93cyBhbmQgY29sdW1uIGxhYmVscwojJyBAcGFyYW0gY29sX2Z1biBDb2xvciBmdW5jdGlvbiBmb3IgdGhlIGhlYXRtYXAgcGFsZXR0ZS4gRGVmYXVsdCBpcyBgaGVhdG1hdF9jb2xfZnVuYAojJyBAcGFyYW0gLi4uIEFkZGl0aW9uYWwgYXJndW1lbnRzIHRvIHBhc3MgdG8gYENvbXBsZXhIZWF0bWFwOjpIZWF0bWFwKClgCiMnCiMnIEByZXR1cm4gQSBsaXN0IG9mIENvbXBsZXhIZWF0bWFwIG9iamVjdHMKY3JlYXRlX2hlYXRtYXBfbGlzdCA8LSBmdW5jdGlvbigKICAgIG1hdHJpeF9saXN0LAogICAgY29sdW1uX3RpdGxlLAogICAgbGFiZWxzX2ZvbnRfc2l6ZSwKICAgIGNvbF9mdW4gPSBoZWF0bWFwX2NvbF9mdW4sCiAgICAuLi4pIHsKICAjIFdlIG9ubHkgd2FudCBvbmUgc2hhcmVkIGxlZ2VuZCBpbiB0aGUgZW5kLCBhcmJpdHJhcmlseSBncmFiIHRoZSBmaXJzdCBvbmUKICBrZWVwX2xlZ2VuZF9uYW1lIDwtIG5hbWVzKG1hdHJpeF9saXN0KVsxXQoKICBoZWF0bWFwX2xpc3QgPC0gbWF0cml4X2xpc3QgfD4KICAgIHB1cnJyOjppbWFwKAogICAgICBcKG1hdCwgbmFtZSkgY3JlYXRlX3NpbmdsZV9oZWF0bWFwKAogICAgICAgIG1hdCwKICAgICAgICBuYW1lLAogICAgICAgIGNvbHVtbl90aXRsZSwKICAgICAgICBsYWJlbHNfZm9udF9zaXplLAogICAgICAgIGtlZXBfbGVnZW5kX25hbWUsCiAgICAgICAgY29sX2Z1biwKICAgICAgICAuLi4KICAgICAgKQogICAgKSB8PgogICAgIyBjb25jYXRlbmF0ZSB2ZXJ0aWNhbGx5IGludG8gSGVhdG1hcExpc3Qgb2JqZWN0CiAgICBwdXJycjo6cmVkdWNlKENvbXBsZXhIZWF0bWFwOjpgJXYlYCkKCiAgcmV0dXJuKGhlYXRtYXBfbGlzdCkKfQoKCiMnIERldGVybWluZSB0aGUgbGFiZWwgZm9udCBzaXplIGJhc2VkIG9uICMgY2hhcmFjdGVycyBpbiBjZWxsIHR5cGUgbGFiZWxzCiMnCiMnIEBwYXJhbSBpbnB1dF9sYWJlbHMgVmVjdG9yIG9mIGNlbGwgdHlwZSBsYWJlbHMKIycKIycgQHJldHVybiBGb250IHNpemUgbnVtZXJpYyBhcyBkZXRlcm1pbmVkIGJ5IGxvbmdlc3QgY2VsbCB0eXBlIGxhYmVsCmZpbmRfbGFiZWxfc2l6ZSA8LSBmdW5jdGlvbihpbnB1dF9sYWJlbHMpIHsKICBsb25nZXN0X25hbWUgPC0gaW5wdXRfbGFiZWxzIHw+CiAgICBzdHJpbmdyOjpzdHJfbGVuZ3RoKCkgfD4KICAgIG1heCgpCgogIGxhYmVsc19mb250X3NpemUgPC0gZHBseXI6OmNhc2Vfd2hlbigKICAgIGxvbmdlc3RfbmFtZSA8IDM1IH4gOS41LAogICAgbG9uZ2VzdF9uYW1lIDwgNDUgfiA4LjUsCiAgICBsb25nZXN0X25hbWUgPCA2MCB+IDcuNSwKICAgIC5kZWZhdWx0ID0gNi41CiAgKQoKICByZXR1cm4obGFiZWxzX2ZvbnRfc2l6ZSkKfQpgYGAKCgpgYGB7cn0KIycgRnVuY3Rpb24gdG8gY2FsY3VsYXRlIG9wdGltYWwgaGVhdG1hcCBwbG90IHZpZXcgaGVpZ2h0CiMnCiMnIEBwYXJhbSByb3dfbmFtZXMgVmVjdG9yIG9mIHJvd25hbWVzCiMnIEBwYXJhbSBjb2xfbmFtZXMgVmVjdG9yIG9mIGNvbHVtbiBuYW1lcwojJyBAcGFyYW0gbl9zcGFjZXJzIE51bWJlciBvZiBzcGFjZXJzIGJldHdlZW4gc3RhY2tlZCBoZWF0bWFwcwojJyBAcGFyYW0gc3BhY2VyX3NpemUgU3BhY2VyIHNpemUgaW4gaW5jaGVzCiMnIEBwYXJhbSBtaW5faGVpZ2h0IE1pbmltaXplIGhlaWdodCByZXF1aXJlZC4gRGVmYXVsdCA0IgojJwojJyBAcmV0dXJuIEhlYXRtYXAgaGVpZ2h0IGluIGluY2hlcwpjYWxjdWxhdGVfcGxvdF9oZWlnaHQgPC0gZnVuY3Rpb24oCiAgICByb3dfbmFtZXMsCiAgICBjb2xfbmFtZXMsCiAgICBuX3NwYWNlcnMsCiAgICBzcGFjZXJfc2l6ZSA9IGhlYXRtYXBfcGFkZGluZywKICAgIG1pbl9oZWlnaHQgPSA0KSB7CiAgIyBmaXJzdCwgYmFzZWQgb24gbnVtYmVyIG9mIGNlbGxzIGluIHJvd19uYW1lczoKICAjICAgNiBjZWxsIHR5cGVzIHRvIGFuIGluY2gKICBoZWF0X2hlaWdodCA8LSBsZW5ndGgocm93X25hbWVzKSAvIDYKCiAgIyBuZXh0LCBiYXNlZCBvbiBuY2hhciBvZiBjb2xfbmFtZXM6CiAgIyAgIDEwIGNoYXJhY3RlcnMgdG8gYW4gaW5jaAogICMgdXNpbmcgc3RyaW5ncjo6c3RyX2xlbmd0aCgpIGluIGNhc2UgY29sX25hbWVzIGlzIGEgZmFjdG9yIHZlY3RvcgogIGhlYXRfaGVpZ2h0IDwtIGhlYXRfaGVpZ2h0ICsgbWF4KHN0cmluZ3I6OnN0cl9sZW5ndGgoY29sX25hbWVzKSkgLyAxMAoKICAjIGZpbmFsbHksIGFkZCBpbiBhbnkgcGFkZGluZwogIGhlYXRfaGVpZ2h0IDwtIGhlYXRfaGVpZ2h0ICsgbl9zcGFjZXJzICogc3BhY2VyX3NpemUKCiAgcmV0dXJuKAogICAgbWF4KGMobWluX2hlaWdodCwgaGVhdF9oZWlnaHQpKQogICkKfQpgYGAKCgpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGVjaG8gPSBGQUxTRX0KIyBkZWZpbmUgbGlicmFyeSBhbmQgc2NlIG9iamVjdApsaWJyYXJ5X2lkIDwtIHBhcmFtcyRsaWJyYXJ5CnByb2Nlc3NlZF9zY2UgPC0gcGFyYW1zJHByb2Nlc3NlZF9zY2UKCiMgY2hlY2sgZm9yIGFubm90YXRpb24gbWV0aG9kcwpoYXNfc2luZ2xlciA8LSAic2luZ2xlciIgJWluJSBtZXRhZGF0YShwcm9jZXNzZWRfc2NlKSRjZWxsdHlwZV9tZXRob2RzCmhhc19jZWxsYXNzaWduIDwtICJjZWxsYXNzaWduIiAlaW4lIG1ldGFkYXRhKHByb2Nlc3NlZF9zY2UpJGNlbGx0eXBlX21ldGhvZHMKaGFzX3N1Ym1pdHRlciA8LSAic3VibWl0dGVyIiAlaW4lIG1ldGFkYXRhKHByb2Nlc3NlZF9zY2UpJGNlbGx0eXBlX21ldGhvZHMgJiYKICAhYWxsKGlzLm5hKHByb2Nlc3NlZF9zY2Ukc3VibWl0dGVyX2NlbGx0eXBlX2Fubm90YXRpb24pKSAjIG1ha2Ugc3VyZSB0aGV5IGFyZW4ndCBhbGwgTkEKCiMgSWYgYXQgbGVhc3QgMSBpcyBwcmVzZW50LCB3ZSBoYXZlIGNlbGwgdHlwZSBhbm5vdGF0aW9ucy4KaGFzX2NlbGx0eXBlcyA8LSBhbnkoaGFzX3NpbmdsZXIsIGhhc19jZWxsYXNzaWduLCBoYXNfc3VibWl0dGVyKQoKIyBjaGVjayBmb3IgdW1hcCBhbmQgY2x1c3RlcnMKaGFzX3VtYXAgPC0gIlVNQVAiICVpbiUgcmVkdWNlZERpbU5hbWVzKHByb2Nlc3NlZF9zY2UpCmhhc19jbHVzdGVycyA8LSAiY2x1c3RlciIgJWluJSBuYW1lcyhjb2xEYXRhKHByb2Nlc3NlZF9zY2UpKQoKIyB3aGF0IGNlbGx0eXBlcyBhcmUgYXZhaWxhYmxlPwphdmFpbGFibGVfY2VsbHR5cGVzIDwtIGMoCiAgaWZlbHNlKGhhc19zdWJtaXR0ZXIsICJTdWJtaXR0ZXIiLCBOQSksCiAgaWZlbHNlKGhhc19zaW5nbGVyLCAiU2luZ2xlUiIsIE5BKSwKICBpZmVsc2UoaGFzX2NlbGxhc3NpZ24sICJDZWxsQXNzaWduIiwgTkEpCikgfD4KICBuYS5vbWl0KCkgfD4KICBhcy5jaGFyYWN0ZXIoKQoKIyB3YXMgY2VsbGFzc2lnbiBydW4/CmNlbGxhc3NpZ25fbm90X3J1biA8LSBjaGVja19jZWxsYXNzaWduX25vdF9ydW4oCiAgaGFzX2NlbGxhc3NpZ24sCiAgY29sRGF0YShwcm9jZXNzZWRfc2NlKQopCgojIFRoaXMgdmFyaWFibGUgbmVlZCB0byBiZSBkZWZpbmVkIGZvciBlZGdlIGNvbmRpdGlvbnMgd2hlbiBjZXJ0YWluIGNlbGwgdHlwZXMKIyAgYXJlbid0IGF2YWlsYWJsZToKIyAgV2hlbiB3ZSBoYXZlIGNodW5rcyB3aXRoIGBldmFsPTxoYXNfbWV0aG9kPmAsIGtuaXRyIHNlZW1zIHRvIG5lZWQgYWxsIG90aGVyCiMgIHZhcmlhYmxlcyB1c2VkIGluIGNodW5rIHBhcmFtcyBkZWZpbmVkLCBpbmNsdWRpbmcgcGxvdCBkaW1lbnNpb24gdmFyaWFibGVzCiMgIHdoaWNoIHdvdWxkIGhhdmUgb25seSBiZWVuIGNyZWF0ZWQgaW4gY2h1bmtzIHdoaWNoIGFsc28gaGFkIGFuIGFzc29jaWF0ZWQKIyAgZXZhbD08aGFzX21ldGhvZD5gLiBTaW5jZSB0aG9zZSBjaHVua3Mgd29uJ3QgaGF2ZSBiZWVuIGV2YWwnZCBpZiBGQUxTRSwgd2UKIyAgbmVlZCB0byBkZWZpbmUgdGhpcyB2YXJpYWJsZSB0byBwcmV2ZW50IGVycm9ycywgYnV0IHRoaXMgdmFsdWUgd2lsbCBuZXZlcgojICBhY3R1YWxseSBiZSB1c2VkLgpwbG90X2hlaWdodCA8LSAxCgojIERldGVybWluZSBpZiBsaWJyYXJ5IGlzIG11bHRpcGxleGVkOgojICBzYW1wbGVfaWQgc2hvdWxkIGJlIGRlZmluZWQgd2l0aCBsZW5ndGggPiAxCnNhbXBsZV9pZCA8LSBtZXRhZGF0YShwcm9jZXNzZWRfc2NlKSRzYW1wbGVfaWQKaGFzX211bHRpcGxleCA8LSBsZW5ndGgoc2FtcGxlX2lkKSA+IDEKYGBgCgo8IS0tIElmIG11bHRpcGxleGVkLCBvcGVuIHdpdGggd2FybmluZyAgLS0+IApgYGB7ciwgZXZhbCA9IGhhc19tdWx0aXBsZXgsIHJlc3VsdHM9J2FzaXMnfQojIGNvbnZlcnQgc2FtcGxlIGlkIHRvIGJ1bGxldCBzZXBhcmF0ZWQgbGlzdAptdWx0aXBsZXhfc2FtcGxlcyA8LSBwYXN0ZTAoIjxsaT4iLCBwYXN0ZShzYW1wbGVfaWQsIGNvbGxhcHNlID0gIjwvbGk+PGxpPiIsICI8L2xpPiIpKQpnbHVlOjpnbHVlKCIKIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC13YXJuaW5nXCI+CgogVGhpcyBsaWJyYXJ5IGlzIG11bHRpcGxleGVkIGFuZCBjb250YWlucyBkYXRhIGZyb20gbW9yZSB0aGFuIG9uZSBzYW1wbGUuCiBEYXRhIGZyb20gdGhlIGZvbGxvd2luZyBzYW1wbGVzIGFyZSBpbmNsdWRlZCBpbiB0aGlzIGxpYnJhcnk6CgogICAge211bHRpcGxleF9zYW1wbGVzfQoKICA8L2Rpdj4KIikKYGBgCgpUaGlzIHJlcG9ydCBjb250YWlucyBhIHN1bW1hcnkgb2YgY2VsbCB0eXBlIGFubm90YXRpb24gcmVzdWx0cyBmb3IgbGlicmFyeSBgciBsaWJyYXJ5X2lkYC4KVGhlIGdvYWwgb2YgdGhpcyByZXBvcnQgaXMgdG8gcHJvdmlkZSBtb3JlIGRldGFpbGVkIGluZm9ybWF0aW9uIGFib3V0IGNlbGwgdHlwZSBhbm5vdGF0aW9uIHJlc3VsdHMgYXMgYW4gaW5pdGlhbCBldmFsdWF0aW9uIG9mIHRoZWlyIHF1YWxpdHkgYW5kIHJlbGlhYmlsaXR5LgoKUGVyZm9ybWluZyBjZWxsIHR5cGUgYW5ub3RhdGlvbiBpcyBhbiBpbmhlcmVudGx5IGNoYWxsZW5naW5nIHRhc2sgd2l0aCBoaWdoIGxldmVscyBvZiB1bmNlcnRhaW50eSwgZXNwZWNpYWxseSB3aGVuIHVzaW5nIGF1dG9tYXRlZCBhbm5vdGF0aW9uIG1ldGhvZHMuCk9uZSB3YXkgdG8gYWRkcmVzcyB0aGlzIGlzIHRvIHVzZSBtdWx0aXBsZSBjZWxsIHR5cGUgYW5ub3RhdGlvbiBhcHByb2FjaGVzIGFuZCBjb21wYXJlIHRoZSByZXN1bHRzLCBhcyB3ZSBoYXZlIGJlZ3VuIHRvIGRvIGluIHRoaXMgcmVwb3J0LgoKV2hlbiBtdWx0aXBsZSBtZXRob2RzIGFubm90YXRlIGEgZ2l2ZW4gY2VsbCBhcyB0aGUgc2FtZSBvciBzaW1pbGFyIGNlbGwgdHlwZSwgdGhpcyBtYXkgcXVhbGl0YXRpdmVseSBpbmRpY2F0ZSBhIG1vcmUgcm9idXN0IGFubm90YXRpb24uCgpOb3RlIHRoYXQgdGhlIGNvbnRlbnRzIG9mIHRoaXMgcmVwb3J0IHdpbGwgdmFyeSBiYXNlZCBvbiB3aGljaCBjZWxsIHR5cGUgYW5ub3RhdGlvbnMgYXJlIHByZXNlbnQuCkZ1cnRoZXIsIGJlIGF3YXJlIHRoYXQgZGlmZmVyZW50IGNlbGwgdHlwZSBhbm5vdGF0aW9uIG1ldGhvZHMgbWF5IGFzc2lnbiBkaWZmZXJlbnQgbGFiZWxzIHRvIHRoZSBzYW1lIG9yIHNpbWlsYXIgY2VsbCB0eXBlIChlLmcuLCB0aGUgZGlmZmVyZW50IHN0cmluZyByZXByZXNlbnRhdGlvbnMgYEIgY2VsbCBuYWl2ZWAgYW5kIGBOYWl2ZSBCIGNlbGxgKSwgZHVlIHRvIHVzZSBvZiBkaWZmZXJlbnQgdW5kZXJseWluZyByZWZlcmVuY2UgZGF0YXNldHMuClBsZWFzZSBub3RlIHRoYXQgYWxsIGNlbGwgdHlwZSBhbm5vdGF0aW9uIHJlZmVyZW5jZSBkYXRhc2V0cyBhcmUgZGVyaXZlZCBmcm9tIG5vcm1hbCAobm90IHR1bW9yKSB0aXNzdWUuCgo8IS0tTm90ZSB0aGF0IHRoZSBzcGVjaWZpYyBjb250ZW50cyBvZiB0aGlzIHJlcG9ydCB3aWxsIGRlcGVuZCBvbiB3aGljaCBjZWxsIHR5cGUgYW5ub3RhdGlvbnMgYXJlIHByZXNlbnQuLS0+CioqVGhpcyBsaWJyYXJ5IGNvbnRhaW5zIHRoZSBmb2xsb3dpbmcgY2VsbCB0eXBlIGFubm90YXRpb25zOioqCgpgYGB7ciByZXN1bHRzPSdhc2lzJ30KIyBidWlsZCB1cCB0aGlzIHN0cmluZyBhcyB3ZSBnbzoKbWV0aG9kc190ZXh0IDwtICIiCgppZiAoaGFzX3N1Ym1pdHRlcikgewogIG1ldGhvZHNfdGV4dCA8LSBnbHVlOjpnbHVlKAogICAgInttZXRob2RzX3RleHR9CiAgICAqIFN1Ym1pdHRlci1wcm92aWRlZCBjZWxsIHR5cGUgYW5ub3RhdGlvbiwgZ2VuZXJhdGVkIGJ5IHRoZSBvcmlnaW5hbCBsYWIgd2hpY2ggcHJvZHVjZWQgdGhpcyBkYXRhLlxuIgogICkKfQoKaWYgKGhhc19zaW5nbGVyKSB7CiAgbWV0aG9kc190ZXh0IDwtIGdsdWU6OmdsdWUoCiAgICAie21ldGhvZHNfdGV4dH0KICAgICogQW5ub3RhdGlvbnMgZnJvbSBbYFNpbmdsZVJgXShodHRwczovL2Jpb2NvbmR1Y3Rvci5vcmcvcGFja2FnZXMvcmVsZWFzZS9iaW9jL2h0bWwvU2luZ2xlUi5odG1sKSwgYSByZWZlcmVuY2UtYmFzZWQgYXBwcm9hY2ggKFtMb29uZXkgX2V0IGFsLl8gMjAxOV0oaHR0cHM6Ly9kb2kub3JnLzEwLjEwMzgvczQxNTkwLTAxOC0wMjc2LXkpKS4KICAgIFRoZSBge21ldGFkYXRhKHByb2Nlc3NlZF9zY2UpJHNpbmdsZXJfcmVmZXJlbmNlfWAgZGF0YXNldCwgb2J0YWluZWQgZnJvbSB0aGUgW2BjZWxsZGV4YCBwYWNrYWdlXShodHRwOi8vYmlvY29uZHVjdG9yLm9yZy9wYWNrYWdlcy9yZWxlYXNlL2RhdGEvZXhwZXJpbWVudC9odG1sL2NlbGxkZXguaHRtbCksIHdhcyB1c2VkIGZvciByZWZlcmVuY2UgYW5ub3RhdGlvbnMuXG4iCiAgKQp9CgppZiAoaGFzX2NlbGxhc3NpZ24pIHsKICBvcmdhbnMgPC0gbWV0YWRhdGEocHJvY2Vzc2VkX3NjZSkkY2VsbGFzc2lnbl9yZWZlcmVuY2Vfb3JnYW5zIHw+CiAgICBzdHJpbmdyOjpzdHJfdG9fbG93ZXIoKQogICMgc3BsaXQgdXAgYW5kIGFkZCBhbiBgYW5kYCBiZWZvcmUgdGhlIGZpbmFsIG9yZ2FuCiAgb3JnYW5zX3N0cmluZyA8LSBzdHJpbmdyOjpzdHJfc3BsaXRfMShvcmdhbnMsIHBhdHRlcm4gPSAiLCAiKSB8PgogICAgc3RyaW5ncjo6c3RyX2ZsYXR0ZW5fY29tbWEobGFzdCA9ICIsIGFuZCAiKQoKICByZWZfbmFtZSA8LSBtZXRhZGF0YShwcm9jZXNzZWRfc2NlKSRjZWxsYXNzaWduX3JlZmVyZW5jZQoKICBtZXRob2RzX3RleHQgPC0gZ2x1ZTo6Z2x1ZSgKICAgICJ7bWV0aG9kc190ZXh0fQogICAgKiBBbm5vdGF0aW9ucyBmcm9tIFtgQ2VsbEFzc2lnbmBdKGh0dHBzOi8vZ2l0aHViLmNvbS9JcnJhdGlvbm9uZS9jZWxsYXNzaWduKSwgYSBtYXJrZXItZ2VuZS1iYXNlZCBhcHByb2FjaCAoW1poYW5nIF9ldCBhbC5fIDIwMTldKGh0dHBzOi8vZG9pLm9yZy8xMC4xMDM4L3M0MTU5Mi0wMTktMDUyOS0xKSkuCiAgICBNYXJrZXIgZ2VuZXMgZm9yIGNlbGwgdHlwZXMgd2VyZSBvYnRhaW5lZCBmcm9tIFtQYW5nbGFvREJdKGh0dHBzOi8vcGFuZ2xhb2RiLnNlLykgYW5kIGNvbXBpbGVkIGludG8gYSByZWZlcmVuY2UgbmFtZWQgYHtyZWZfbmFtZX1gLgogICAgVGhpcyByZWZlcmVuY2UgaW5jbHVkZXMgdGhlIGZvbGxvd2luZyBvcmdhbnMgYW5kIHRpc3N1ZSBjb21wYXJ0bWVudHM6IHtvcmdhbnNfc3RyaW5nfS5cbiIKICApCn0KCmdsdWU6OmdsdWUoInttZXRob2RzX3RleHR9IikKYGBgCgpgYGB7ciBldmFsPWNlbGxhc3NpZ25fbm90X3J1biwgcmVzdWx0cz0nYXNpcyd9CmdsdWU6OmdsdWUoIgogICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtaW5mb1wiPgogICBDZWxsIHR5cGUgYW5ub3RhdGlvbiB3aXRoIFtgQ2VsbEFzc2lnbmBdKGh0dHBzOi8vZ2l0aHViLmNvbS9JcnJhdGlvbm9uZS9jZWxsYXNzaWduKSwgYSBtYXJrZXItZ2VuZS1iYXNlZCBhcHByb2FjaCAoW1poYW5nIF9ldCBhbC5fIDIwMTldKGh0dHBzOi8vZG9pLm9yZy8xMC4xMDM4L3M0MTU5Mi0wMTktMDUyOS0xKSksIHdhcyBhdHRlbXB0ZWQgYnV0IG5vdCBydW4gZHVlIHRvIGFuIGluc3VmZmljaWVudCBudW1iZXIgb2YgY2VsbHMuCiAgPC9kaXY+CiIpCmBgYAoKCiMgU2FtcGxlIG1ldGFkYXRhIAoKVGhlIGJlbG93IHRhYmxlIHN1bW1hcml6ZXMgY2xpbmljYWwgbWV0YWRhdGEgZm9yIHRoZSBzYW1wbGUgYXNzb2NpYXRlZCB3aXRoIHRoaXMgbGlicmFyeS4gCkJsdWUgaHlwZXJsaW5rcyBhcmUgcHJlc2VudCBmb3IgYW55IHRlcm1zIHdpdGggYW4gb250b2xvZ3kgdGVybSBpZGVudGlmaWVyIGFzc29jaWF0ZWQgd2l0aCB0aGUgZGlzcGxheWVkIGh1bWFuIHJlYWRhYmxlIHZhbHVlLiAKVGhlc2UgbGlua3Mgd2lsbCBkaXJlY3QgeW91IHRvIGEgd2ViIHBhZ2Ugd2l0aCBpbmZvcm1hdGlvbiBhYm91dCB0aGF0IG9udG9sb2d5IHRlcm0gaWRlbnRpZmllci4gICAKCmBgYHtyfQojIGV4dHJhY3Qgc2NlIG1ldGFkYXRhIGNvbnRhaW5pbmcgcHJvY2Vzc2luZyBpbmZvcm1hdGlvbiBhcyB0YWJsZQpwcm9jZXNzZWRfbWV0YSA8LSBtZXRhZGF0YShwcm9jZXNzZWRfc2NlKQoKIyBpZiBkYXRhIGlzIG5vdCBtdWx0aXBsZXhlZCwgcHJpbnQgb3V0IHNhbXBsZSBtZXRhZGF0YQppZiAoIWhhc19tdWx0aXBsZXgpIHsKICBwcmludF9zYW1wbGVfbWV0YWRhdGEocHJvY2Vzc2VkX21ldGEpCn0gZWxzZSB7CiAgIyBvdGhlcndpc2UgcHJpbnQgb3V0IGFuIGluZm8gYm94IHRoYXQgbm8gc2FtcGxlIG1ldGFkYXRhIHdpbGwgYmUgZGlzcGxheWVkCiAga25pdHI6OmFzaXNfb3V0cHV0KAogICAgZ2x1ZTo6Z2x1ZSgiCiAgICAgIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1pbmZvXCI+CgogICAgICBUaGlzIGxpYnJhcnkgaXMgbXVsdGlwbGV4ZWQgYW5kIGNvbnRhaW5zIGRhdGEgZnJvbSBtb3JlIHRoYW4gb25lIHNhbXBsZS4KICAgICAgRGVtdWx0aXBsZXhpbmcgaGFzIG5vdCBiZWVuIHBlcmZvcm1lZCwgc28gc2FtcGxlIG1ldGFkYXRhIHdpbGwgbm90IGJlIGRpc3BsYXllZC4KICAgICAgPC9kaXY+CiAgICAiKQogICkKfQpgYGAKCgo8IS0tLS0tLS0gQ2FsbCB0aGUgY2VsbHR5cGVzX3FjIHJlcG9ydCBzZWN0aW9uIGZyb20gdGhlIG1haW4gcmVwb3J0IC0tLS0tLS0tLS0tPgpgYGB7ciwgY2hpbGQ9J2NlbGx0eXBlc19xYy5ybWQnfQpgYGAKCgojIENlbGwgbGFiZWwgY29tcGFyaXNvbiBwbG90cwoKVGhpcyBzZWN0aW9uIGRpc3BsYXlzIGhlYXRtYXBzIGNvbXBhcmluZyBjZWxsIGxhYmVscyBmcm9tIHZhcmlvdXMgbWV0aG9kcy4KCldlIHVzZSB0aGUgW0phY2NhcmQgc2ltaWxhcml0eSBpbmRleF0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSmFjY2FyZF9pbmRleCkgdG8gZGlzcGxheSB0aGUgYWdyZWVtZW50IGJldHdlZW4gYmV0d2VlbiBwYWlycyBvZiBsYWJlbHMgYXNzaWduZWQgYnkgZGlmZmVyZW50IGFubm90YXRpb24gbWV0aG9kcy4KClRoZSBKYWNjYXJkIGluZGV4IHJlZmxlY3RzIHRoZSBkZWdyZWUgb2Ygb3ZlcmxhcCBiZXR3ZWVuIHRoZSB0d28gbGFiZWxzIGFuZCByYW5nZXMgZnJvbSAwIHRvIDEuCgoqIElmIHRoZSBsYWJlbHMgYXJlIGFzc2lnbmVkIHRvIGlkZW50aWNhbCBzZXRzIG9mIGNlbGxzLCB0aGUgSmFjY2FyZCBpbmRleCB3aWxsIGJlIDEuCiogSWYgdGhlIGxhYmVscyBhcmUgYXNzaWduZWQgdG8gY29tcGxldGVseSBub24tb3ZlcmxhcHBpbmcgc2V0cyBvZiBjZWxscywgdGhlIEphY2NhcmQgaW5kZXggd2lsbCBiZSAwLgoKSGlnaCBhZ3JlZW1lbnQgYmV0d2VlbiBtZXRob2RzIHF1YWxpdGF0aXZlbHkgaW5kaWNhdGVzIGhpZ2hlciBjb25maWRlbmNlIGluIHRoZSBjZWxsIHR5cGUgYW5ub3RhdGlvbi4KCgoKCgo8IS0tIElmIG11bHRpcGxleGVkLCBzaG93IGluZm8gYWxlcnQgaW5zdGVhZCBvZiB0aGlzIGhlYXRtYXAgLS0+IApgYGB7ciwgZXZhbCA9IGhhc19tdWx0aXBsZXgsIHJlc3VsdHM9J2FzaXMnfQpnbHVlOjpnbHVlKCIKIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1pbmZvXCI+CgogIE5vIGhlYXRtYXAgY29tcGFyaW5nIGNsdXN0ZXIgYW5kIGNlbGwgdHlwZSBhbm5vdGF0aW9uIGxhYmVscyBpcyBzaG93biBiZWNhdXNlIHRoZSBwcmVzZW5jZSBvZiBtdWx0aXBsZSBzYW1wbGVzIG1heSBjb25mb3VuZCBjbHVzdGVyIGFzc2lnbm1lbnQuCgogIDwvZGl2PgoiKQpgYGAKCjwhLS0gSWYgbm90IG11bHRpcGxleGVkLCBzaG93IHRoZSBoZWFkZXIsIHRleHQsIGFuZCBoZWF0bWFwIC0tPiAKYGBge3IsIGV2YWwgPSAhaGFzX211bHRpcGxleCAmJiBoYXNfY2x1c3RlcnMsIHJlc3VsdHM9J2FzaXMnfQpnbHVlOjpnbHVlKCIKICAjIyBVbnN1cGVydmlzZWQgY2x1c3RlcmluZwoKICBIZXJlIHdlIHNob3cgdGhlIGxhYmVscyBmcm9tIHVuc3VwZXJ2aXNlZCBjbHVzdGVyaW5nIGNvbXBhcmVkIHRvIGNlbGwgdHlwZSBhbm5vdGF0aW9ucy4KICBDbHVzdGVyIGFzc2lnbm1lbnQgd2FzIHBlcmZvcm1lZCB1c2luZyB0aGUgYHttZXRhZGF0YShwcm9jZXNzZWRfc2NlKSRjbHVzdGVyX2FsZ29yaXRobX1gIGFsZ29yaXRobS4KIikKCiMgQ2FsY3VsYXRlIGFsbCBqYWNjYXJkIG1hdHJpY2VzIG9mIGludGVyZXN0IGZvciBpbnB1dCB0byBoZWF0bWFwCmphY2NhcmRfY2x1c3Rlcl9tYXRyaWNlcyA8LSBhdmFpbGFibGVfY2VsbHR5cGVzIHw+CiAgc3RyaW5ncjo6c3RyX3RvX2xvd2VyKCkgfD4KICBwdXJycjo6c2V0X25hbWVzKGF2YWlsYWJsZV9jZWxsdHlwZXMpIHw+CiAgcHVycnI6Om1hcChcKG5hbWUpIHsKICAgIG1ha2VfamFjY2FyZF9tYXRyaXgoCiAgICAgIGNlbGx0eXBlX2RmLAogICAgICAiY2x1c3RlciIsCiAgICAgIGdsdWU6OmdsdWUoIntuYW1lfV9jZWxsdHlwZV9hbm5vdGF0aW9uIikKICAgICkKICB9KQoKYWxsX2NlbGx0eXBlcyA8LSBqYWNjYXJkX2NsdXN0ZXJfbWF0cmljZXMgfD4KICBwdXJycjo6bWFwKGNvbG5hbWVzKSB8PgogIHVubGlzdCgpCgpwbG90X2hlaWdodCA8LSBjYWxjdWxhdGVfcGxvdF9oZWlnaHQoCiAgYWxsX2NlbGx0eXBlcywKICB1bmlxdWUoY2VsbHR5cGVfZGYkY2x1c3RlciksCiAgbGVuZ3RoKGphY2NhcmRfY2x1c3Rlcl9tYXRyaWNlcykgLSAxCikKYGBgCgoKYGBge3IsIGV2YWwgPSAhaGFzX211bHRpcGxleCAmJiBoYXNfY2x1c3RlcnMsIGZpZy5oZWlnaHQgPSBwbG90X2hlaWdodCwgZmlnLndpZHRoID0gOC41LCB3YXJuaW5nID0gRkFMU0V9CmphY2NhcmRfY2x1c3Rlcl9tYXRyaWNlcyB8PgogIGNyZWF0ZV9oZWF0bWFwX2xpc3QoCiAgICBjb2x1bW5fdGl0bGUgPSAiQ2x1c3RlcnMiLAogICAgbGFiZWxzX2ZvbnRfc2l6ZSA9IGZpbmRfbGFiZWxfc2l6ZShhbGxfY2VsbHR5cGVzKSwKICAgICMjIGFkZGl0aW9uYWwgYXJndW1lbnRzCiAgICBjb2x1bW5fbmFtZXNfcm90ID0gMAogICkgfD4KICBDb21wbGV4SGVhdG1hcDo6ZHJhdygKICAgIGhlYXRtYXBfbGVnZW5kX3NpZGUgPSAiYm90dG9tIgogICkKYGBgCgoKCjwhLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gU3VibWl0dGVyIGhlYXRtYXBzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0+CmBgYHtyLCBldmFsID0gaGFzX3N1Ym1pdHRlciAmIChoYXNfY2VsbGFzc2lnbiB8IGhhc19zaW5nbGVyKX0KIyBkb24ndCBjb21wYXJlIHN1Ym1pdHRlciB0byBzdWJtaXR0ZXIKYXZhaWxhYmxlX2NlbGx0eXBlcyA8LSBhdmFpbGFibGVfY2VsbHR5cGVzWyEoYXZhaWxhYmxlX2NlbGx0eXBlcyA9PSAiU3VibWl0dGVyIildCgptZXRob2RzX3N0cmluZyA8LSBhdmFpbGFibGVfY2VsbHR5cGVzIHw+CiAgc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKCJeIiwgImAiKSB8PgogIHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCgiJCIsICJgIikgfD4KICBzdHJpbmdyOjpzdHJfZmxhdHRlbl9jb21tYSgiLCBhbmQgIikKCmtuaXRyOjphc2lzX291dHB1dCgKICBnbHVlOjpnbHVlKAogICAgIiMjIFN1Ym1pdHRlci1wcm92aWRlZCBhbm5vdGF0aW9ucwoKICBUaGlzIHNlY3Rpb24gZGlzcGxheXMgaGVhdG1hcHMgY29tcGFyaW5nIHN1Ym1pdHRlci1wcm92aWRlZCBjZWxsIHR5cGUgYW5ub3RhdGlvbnMgdG8gdGhvc2Ugb2J0YWluZWQgZnJvbSB7bWV0aG9kc19zdHJpbmd9LiIKICApCikKYGBgCgpgYGB7ciwgZXZhbCA9IGhhc19zdWJtaXR0ZXIgJiAoaGFzX2NlbGxhc3NpZ24gfCBoYXNfc2luZ2xlcil9CiMgY2FsY3VsYXRlIG1hdHJpY2VzIGNvbXBhcmluZyB0byBzdWJtaXR0ZXIKamFjY2FyZF9zdWJtaXR0ZXJfbWF0cmljZXMgPC0gYXZhaWxhYmxlX2NlbGx0eXBlcyB8PgogIHN0cmluZ3I6OnN0cl90b19sb3dlcigpIHw+CiAgcHVycnI6Om1hcChcKG5hbWUpIHsKICAgIG1ha2VfamFjY2FyZF9tYXRyaXgoCiAgICAgIGNlbGx0eXBlX2RmLAogICAgICAic3VibWl0dGVyX2NlbGx0eXBlX2Fubm90YXRpb24iLAogICAgICBnbHVlOjpnbHVlKCJ7bmFtZX1fY2VsbHR5cGVfYW5ub3RhdGlvbiIpCiAgICApCiAgfSkgfD4KICBwdXJycjo6c2V0X25hbWVzKGF2YWlsYWJsZV9jZWxsdHlwZXMpCgojIGhvdyBtYW55IGNlbGwgdHlwZXM/CmFsbF9jZWxsdHlwZXMgPC0gamFjY2FyZF9zdWJtaXR0ZXJfbWF0cmljZXMgfD4KICBwdXJycjo6bWFwKGNvbG5hbWVzKSB8PgogIHVubGlzdCgpCgpwbG90X2hlaWdodCA8LSBjYWxjdWxhdGVfcGxvdF9oZWlnaHQoCiAgYWxsX2NlbGx0eXBlcywKICB1bmlxdWUoY2VsbHR5cGVfZGYkc3VibWl0dGVyX2NlbGx0eXBlX2Fubm90YXRpb24pLAogIGxlbmd0aChqYWNjYXJkX3N1Ym1pdHRlcl9tYXRyaWNlcykgLSAxCikKYGBgCgpgYGB7ciwgZXZhbCA9IGhhc19zdWJtaXR0ZXIgJiAoaGFzX2NlbGxhc3NpZ24gfCBoYXNfc2luZ2xlciksIGZpZy5oZWlnaHQgPSBwbG90X2hlaWdodCwgZmlnLndpZHRoID0gOC41LCB3YXJuaW5nID0gRkFMU0V9CmphY2NhcmRfc3VibWl0dGVyX21hdHJpY2VzIHw+CiAgY3JlYXRlX2hlYXRtYXBfbGlzdCgKICAgIGNvbHVtbl90aXRsZSA9ICJTdWJtaXR0ZXItcHJvdmlkZWQgYW5ub3RhdGlvbnMiLAogICAgbGFiZWxzX2ZvbnRfc2l6ZSA9IGZpbmRfbGFiZWxfc2l6ZShhbGxfY2VsbHR5cGVzKSwKICAgICMgYWRkaXRpb25hbCBhcmd1bWVudHMKICAgIGNvbHVtbl9uYW1lc19yb3QgPSA5MAogICkgfD4KICBDb21wbGV4SGVhdG1hcDo6ZHJhdygKICAgIGhlYXRtYXBfbGVnZW5kX3NpZGUgPSAiYm90dG9tIgogICkKYGBgCgoKPCEtLS0tLS0tLS0tLS0tLS0tLS0tLS0tIFNpbmdsZVIvQ2VsbEFzc2lnbiBoZWF0bWFwICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLT4KYGBge3IsIGV2YWwgPSBoYXNfY2VsbGFzc2lnbiAmIGhhc19zaW5nbGVyLCBmaWcuaGVpZ2h0PTcsIGZpZy53aWR0aD04fQprbml0cjo6YXNpc19vdXRwdXQoIgojIyBBdXRvbWF0ZWQgYW5ub3RhdGlvbnMKClRoaXMgc2VjdGlvbiBkaXNwbGF5cyBhIGhlYXRtYXAgZGlyZWN0bHkgY29tcGFyaW5nIGBTaW5nbGVSYCBhbmQgYENlbGxBc3NpZ25gIGNlbGwgdHlwZSBhbm5vdGF0aW9ucy4KTm90ZSB0aGF0IGR1ZSB0byBkaWZmZXJlbnQgYW5ub3RhdGlvbnMgcmVmZXJlbmNlcywgdGhlc2UgbWV0aG9kcyBtYXkgdXNlIGRpZmZlcmVudCBuYW1lcyBmb3Igc2ltaWxhciBjZWxsIHR5cGVzLgoiKQoKIyBTZXQgcGxvdCBkaW1lbnNpb25zIGJhc2VkIG9uIG51bWJlciBvZiBTaW5nbGVSIGNlbGwgdHlwZXMKYWxsX2NlbGx0eXBlcyA8LSBsZXZlbHMoY2VsbHR5cGVfZGYkc2luZ2xlcl9jZWxsdHlwZV9hbm5vdGF0aW9uKQpwbG90X2hlaWdodCA8LSBjYWxjdWxhdGVfcGxvdF9oZWlnaHQoCiAgdW5pcXVlKGNlbGx0eXBlX2RmJHNpbmdsZXJfY2VsbHR5cGVfYW5ub3RhdGlvbiksCiAgdW5pcXVlKGNlbGx0eXBlX2RmJGNlbGxhc3NpZ25fY2VsbHR5cGVfYW5ub3RhdGlvbiksCiAgMAopCmBgYAoKCmBgYHtyLCBldmFsID0gaGFzX2NlbGxhc3NpZ24gJiBoYXNfc2luZ2xlciwgZmlnLmhlaWdodCA9IHBsb3RfaGVpZ2h0LCBmaWcud2lkdGggPSA4LjV9CiMgQ2FsY3VsYXRlIGphY2NhcmQgbWF0cml4CnNpbmdsZXJfY2VsbGFzc2lnbl9tYXRyaXggPC0gbWFrZV9qYWNjYXJkX21hdHJpeCgKICBjZWxsdHlwZV9kZiwKICAic2luZ2xlcl9jZWxsdHlwZV9hbm5vdGF0aW9uIiwKICAiY2VsbGFzc2lnbl9jZWxsdHlwZV9hbm5vdGF0aW9uIgopCgpjcmVhdGVfc2luZ2xlX2hlYXRtYXAoCiAgc2luZ2xlcl9jZWxsYXNzaWduX21hdHJpeCwKICByb3dfdGl0bGUgPSAiQ2VsbEFzc2lnbiBhbm5vdGF0aW9ucyIsCiAgY29sdW1uX3RpdGxlID0gIlNpbmdsZVIgYW5ub3RhdGlvbnMiLAogIGxhYmVsc19mb250X3NpemUgPSBmaW5kX2xhYmVsX3NpemUoYWxsX2NlbGx0eXBlcyksCiAga2VlcF9sZWdlbmRfbmFtZSA9ICJDZWxsQXNzaWduIGFubm90YXRpb25zIiwKICBjb2xfZnVuID0gaGVhdG1hcF9jb2xfZnVuLAogICMgYWRkaXRpb25hbCBhcmd1bWVudHMKICBjb2x1bW5fbmFtZXNfcm90ID0gOTAKKSB8PgogIENvbXBsZXhIZWF0bWFwOjpkcmF3KAogICAgaGVhdG1hcF9sZWdlbmRfc2lkZSA9ICJib3R0b20iCiAgKQpgYGAKCjwhLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBEaWFnbm9zdGljIHBsb3RzICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0+CmBgYHtyLCBldmFsID0gaGFzX3NpbmdsZXIgfCBoYXNfY2VsbGFzc2lnbiB9CmtuaXRyOjphc2lzX291dHB1dCgiCiMgUXVhbGl0eSBhc3Nlc3NtZW50cyBvZiBhdXRvbWF0ZWQgYW5ub3RhdGlvbnMKIikKYGBgCgoKPCEtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gU2luZ2xlUiBkZWx0YSBtZWRpYW4gIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLT4KYGBge3IsIGV2YWwgPSBoYXNfc2luZ2xlcn0Ka25pdHI6OmFzaXNfb3V0cHV0KCIKIyMgYFNpbmdsZVJgIGFubm90YXRpb25zCgpUbyBhc3Nlc3MgdGhlIHF1YWxpdHkgb2YgYFNpbmdsZVJgIGNlbGwgdHlwZSBhbm5vdGF0aW9ucywgd2UgdXNlIHRoZSBkZWx0YSBtZWRpYW4gc3RhdGlzdGljLgoKLSBEZWx0YSBtZWRpYW4gaXMgY2FsY3VsYXRlZCBmb3IgZWFjaCBjZWxsIGFzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIGBTaW5nbGVSYCBzY29yZSBvZiB0aGUgYW5ub3RhdGVkIGNlbGwgdHlwZSBsYWJlbCBhbmQgdGhlIG1lZGlhbiBzY29yZSBvZiB0aGUgb3RoZXIgY2VsbCB0eXBlIGxhYmVscyBpbiB0aGUgcmVmZXJlbmNlIGRhdGFzZXQuCi0gSGlnaGVyIGRlbHRhIG1lZGlhbiB2YWx1ZXMgaW5kaWNhdGUgaGlnaGVyIHF1YWxpdHkgY2VsbCB0eXBlIGFubm90YXRpb25zLgogIC0gVmFsdWVzIGNhbiByYW5nZSBmcm9tIDAtMS4KICAtIE5vdGUgdGhhdCB0aGVyZSBpcyBubyB1bml2ZXJzYWwgdGhyZXNob2xkIGZvciBjYWxsaW5nIGFic29sdXRlIGhpZ2ggdnMuIGxvdyBxdWFsaXR5LCBhcyBkZXNjcmliZWQgaW4gdGhlIFtgU2luZ2xlUmAgYm9vayBzZWN0aW9uIG9uICdBbm5vdGF0aW9uIGRpYWdub3N0aWNzJ10oaHR0cHM6Ly9iaW9jb25kdWN0b3Iub3JnL2Jvb2tzL3JlbGVhc2UvU2luZ2xlUkJvb2svYW5ub3RhdGlvbi1kaWFnbm9zdGljcy5odG1sI2Fubm90YXRpb24tZGlhZ25vc3RpY3MpLgoKWW91IGNhbiBpbnRlcnByZXQgdGhpcyBwbG90IGFzIGZvbGxvd3M6CgotIEVhY2ggcG9pbnQgcmVwcmVzZW50cyB0aGUgZGVsdGEgbWVkaWFuIHN0YXRpc3RpYyBvZiBhIGdpdmVuIGNlbGwgd2hvc2UgYFNpbmdsZVJgIGFubm90YXRpb24gaXMgc2hvd24gb24gdGhlIHktYXhpcy4KLSBUaGUgcG9pbnQgc3R5bGUgaW5kaWNhdGVzIGBTaW5nbGVSYCdzIHF1YWxpdHkgYXNzZXNzbWVudCBvZiB0aGUgYW5ub3RhdGlvbjoKICAtIEhpZ2gtcXVhbGl0eSBjZWxsIGFubm90YXRpb25zIGFyZSBzaG93biBhcyBjbG9zZWQgcG9pbnRzLgogIC0gTG93LXF1YWxpdHkgY2VsbCBhbm5vdGF0aW9ucyBhcmUgc2hvd24gYXMgb3BlbiBwb2ludHMuCiAgSW4gb3RoZXIgc2VjdGlvbnMgb2YgdGhpcyByZXBvcnQsIHRoZXNlIGNlbGxzIGFyZSBsYWJlbGVkIGFzIGBVbmtub3duIGNlbGwgdHlwZXNgLgogIC0gRm9yIG1vcmUgaW5mb3JtYXRpb24gb24gaG93IGBTaW5nbGVSYCBjYWxjdWxhdGVzIGFubm90YXRpb24gcXVhbGl0eSwgcGxlYXNlIHJlZmVyIHRvIFt0aGlzIGBTaW5nbGVSYCBkb2N1bWVudGF0aW9uXShodHRwczovL3JkcnIuaW8vYmlvYy9TaW5nbGVSL21hbi9wcnVuZVNjb3Jlcy5odG1sKS4KLSBEaWFtb25kcyByZXByZXNlbnQgdGhlIG1lZGlhbiBvZiB0aGUgZGVsdGEgbWVkaWFuIHN0YXRpc3RpYyBzcGVjaWZpY2FsbHkgYW1vbmcgaGlnaC1xdWFsaXR5IGFubm90YXRpb25zIGZvciB0aGUgZ2l2ZW4gY2VsbCB0eXBlIGFubm90YXRpb24uCiIpCmBgYAoKCmBgYHtyLCBldmFsID0gaGFzX3NpbmdsZXIsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiMgUHJlcGFyZSBTaW5nbGVSIHNjb3JlcyBmb3IgcGxvdAoKIyBleHRyYWN0IHNjb3JlcyBpbnRvIG1hdHJpeApzaW5nbGVyX3Njb3JlcyA8LSBtZXRhZGF0YShwcm9jZXNzZWRfc2NlKSRzaW5nbGVyX3Jlc3VsdCRzY29yZXMKCiMgQ3JlYXRlIGRhdGEgZnJhbWUgZm9yIHBsb3R0aW5nIHdpdGggZGVsdGEgbWVkaWFuIGFuZCB0aGUgZnVsbCAqbm9uLXBydW5lZCogY2VsbCBsYWJlbHMKZGVsdGFfbWVkaWFuX2RmIDwtIHRpYmJsZTo6dGliYmxlKAogIGRlbHRhX21lZGlhbiA9IHJvd01heHMoc2luZ2xlcl9zY29yZXMpIC0gcm93TWVkaWFucyhzaW5nbGVyX3Njb3JlcyksCiAgIyBOZWVkIHRvIGdyYWIgdGhlIG5vbi1wcnVuZWQgbGFiZWwgZm9yIHRoaXMgcGxvdAogIGZ1bGxfbGFiZWxzID0gbWV0YWRhdGEocHJvY2Vzc2VkX3NjZSkkc2luZ2xlcl9yZXN1bHQkbGFiZWxzLAogICMgaWYgcHJ1bmVkLmxhYmVscyBhcmUgTkEgPT0+IGxvdyBjb25maWRlbmNlCiAgIyBzbywgbmVnYXRlIGZvciB0aGlzIHZhcmlhYmxlOgogIGNvbmZpZGVudCA9ICFpcy5uYShtZXRhZGF0YShwcm9jZXNzZWRfc2NlKSRzaW5nbGVyX3Jlc3VsdCRwcnVuZWQubGFiZWxzKQopIHw+CiAgZHBseXI6Om11dGF0ZSgKICAgIGNvbmZpZGVudCA9IGlmZWxzZShjb25maWRlbnQsICJIaWdoLXF1YWxpdHkiLCAiTG93LXF1YWxpdHkiKQogICkKCiMgSWYgb250b2xvZ2llcyB3ZXJlIHVzZWQgZm9yIGBmdWxsX2xhYmVsc2AsIHdlJ2xsIG5lZWQgdG8gbWFwIGJhY2sgdG8gY2VsbCB0eXBlIG5hbWVzCiMgIGZvciB0aGUgcGxvdCBpdHNlbGYuCmlmICgic2luZ2xlcl9jZWxsdHlwZV9vbnRvbG9neSIgJWluJSBuYW1lcyhjZWxsdHlwZV9kZikpIHsKICAjIHdlIHVzZSBpbm5lcl9qb2luIGIvYyB0aGUgYWJvdmUgdGliYmxlIGRvZXMgTk9UIGNvbnRhaW4gIlVua25vd24gY2VsbCB0eXBlIiwgd2hpY2gKICAjICB3ZSBkbyBub3Qgd2FudCB0byBkaXNwbGF5IGhlcmUKICBkZWx0YV9tZWRpYW5fZGYgPC0gZGVsdGFfbWVkaWFuX2RmIHw+CiAgICBkcGx5cjo6aW5uZXJfam9pbigKICAgICAgdGliYmxlOjp0aWJibGUoCiAgICAgICAgZnVsbF9sYWJlbHMgPSBjZWxsdHlwZV9kZiRzaW5nbGVyX2NlbGx0eXBlX29udG9sb2d5LAogICAgICAgIGNlbGx0eXBlID0gY2VsbHR5cGVfZGYkc2luZ2xlcl9jZWxsdHlwZV9hbm5vdGF0aW9uCiAgICAgICkgfD4gZHBseXI6OmRpc3RpbmN0KCkKICAgICkgfD4KICAgIGRwbHlyOjpzZWxlY3QoLWZ1bGxfbGFiZWxzKQp9IGVsc2UgewogICMgb3RoZXJ3aXNlLCBmdWxsX2xhYmVscyBhbHJlYWR5IGNvbnRhaW4gd2hhdCB3ZSB3YW50IHRvIHBsb3QsIHNvIGp1c3QgcmVuYW1lIGl0CiAgZGVsdGFfbWVkaWFuX2RmIDwtIGRlbHRhX21lZGlhbl9kZiB8PgogICAgZHBseXI6OnJlbmFtZShjZWxsdHlwZSA9IGZ1bGxfbGFiZWxzKQogICMgc3RpbGwgbmVlZCB0byBhZGQgbGV2ZWxzOgogICMgTm90ZSB0aGF0IHRoZSBsZXZlbCAiVW5rbm93biBjZWxsIHR5cGUiIHdpbGwgc3RpbGwgYmUgcHJlc2VudCwgYnV0IHRoZXJlIGlzIG5vIHN1Y2ggdmFsdWUgaW4gdGhlIGRhdGEsIHNvIGl0IHdvbid0IG1hdHRlcgogIGxldmVscyhkZWx0YV9tZWRpYW5fZGYkY2VsbHR5cGUpIDwtIGxldmVscyhjZWxsdHlwZV9kZiRzaW5nbGVyX2NlbGx0eXBlX2Fubm90YXRpb24pCn0KCiMgRW5zdXJlIHdlIGhhdmUgbm8gIlVua25vd24gY2VsbCB0eXBlIiB2YWx1ZXMgbGVmdDoKaWYgKGFueShkZWx0YV9tZWRpYW5fZGYkY2VsbHR5cGUgPT0gIlVua25vd24gY2VsbCB0eXBlIikpIHsKICBzdG9wKCJGYWlsZWQgdG8gcHJvY2VzcyBTaW5nbGVSIGRhdGEgZm9yIGRpYWdub3N0aWMgcGxvdC4iKQp9CgojIGFkZCBjb2x1bW4gd2l0aCBvcmRlcmVkIGxldmVscyB3aXRoIHdyYXBwZWQgbGFiZWxzIGZvciB2aXN1YWxpemF0aW9uCmRlbHRhX21lZGlhbl9kZiRhbm5vdGF0aW9uX3dyYXBwZWQgPC0gZmFjdG9yKAogIGRlbHRhX21lZGlhbl9kZiRjZWxsdHlwZSwKICAjIHJldigpIHNvIGxhcmdlIGdyb3VwcyBhcmUgYXQgdGhlIFRPUCBvZiB0aGUgcGxvdAogIGxldmVscyA9IHJldihsZXZlbHMoZGVsdGFfbWVkaWFuX2RmJGNlbGx0eXBlKSksCiAgbGFiZWxzID0gcmV2KHN0cmluZ3I6OnN0cl93cmFwKGxldmVscyhkZWx0YV9tZWRpYW5fZGYkY2VsbHR5cGUpLCAzMCkpCikKCiMgU3Vic2V0IHRoZSBkYXRhIHRvIGp1c3QgY29uZmlkZW50IHBvaW50cyBmb3IgbWVkaWFuKy8tSVFSCmRlbHRhX21lZGlhbl9jb25maWRlbnRfZGYgPC0gZGVsdGFfbWVkaWFuX2RmIHw+CiAgZHBseXI6OmZpbHRlcihjb25maWRlbnQgPT0gIkhpZ2gtcXVhbGl0eSIpCgojIERldGVybWluZSBoZWlnaHQgZm9yIHBsb3QgYXJlYSBiYXNlZCBvbiBudW1iZXIgb2YgY2VsbHMKcGxvdF9oZWlnaHQgPC0gbGVuZ3RoKHVuaXF1ZShkZWx0YV9tZWRpYW5fZGYkY2VsbHR5cGUpKSAvIDIuNQpgYGAKCmBgYHtyLCBldmFsID0gaGFzX3NpbmdsZXIsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGZpZy5oZWlnaHQgPSBwbG90X2hlaWdodCwgZmlnLndpZHRoID0gOH0KIyBQbG90IGRlbHRhX21lZGlhbiBhY3Jvc3MgY2VsbHR5cGVzIGNvbG9yZWQgYnkgcHJ1bmluZwpnZ3Bsb3QoZGVsdGFfbWVkaWFuX2RmKSArCiAgYWVzKAogICAgeCA9IGRlbHRhX21lZGlhbiwKICAgIHkgPSBhbm5vdGF0aW9uX3dyYXBwZWQsCiAgICBzaGFwZSA9IGNvbmZpZGVudCwKICAgIGFscGhhID0gY29uZmlkZW50CiAgKSArCiAgZ2dmb3JjZTo6Z2VvbV9zaW5hKAogICAgc2l6ZSA9IDAuOCwKICAgIGNvbG9yID0gImJsYWNrIiwgIyB3aWxsIGdldCBhcHBsaWVkIHRvIGFsbCBjb25maWRlbnQgcG9pbnRzIGFuZCBub24tY29uZmlkZW50IG91dGxpbmUKICAgIGZpbGwgPSAid2hpdGUiLCAjIHdpbGwgYXBwbHkgdG8gbm9uLWNvbmZpZGVudCBmaWxsIG9ubHkKICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjA1KSAjIEtlZXAgYm90aCB0eXBlcyBvZiBwb2ludHMgbW9zdGx5IGluIGxpbmUKICApICsKICAjIEhhbmRsZSBwb2ludHMgYWVzdGhldGljczoKICAjICBjb25maWRlbnQgYXJlIGNsb3NlZCBibGFjayB3aXRoIGFscGhhID0gMC41CiAgIyAgbm90IGNvbmZpZGVudCBhcmUgb3BlbiBibGFjayB3aXRoIGFscGhhID0gMQogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBjKDE5LCAyMSkpICsKICBzY2FsZV9hbHBoYV9tYW51YWwodmFsdWVzID0gYygwLjUsIDEpKSArCiAgbGFicygKICAgIHggPSAiRGVsdGEgbWVkaWFuIHN0YXRpc3RpYyIsCiAgICB5ID0gIkNlbGwgdHlwZSBhbm5vdGF0aW9uIiwKICAgIHNoYXBlID0gIkNlbGwgdHlwZSBhbm5vdGF0aW9uIHF1YWxpdHkiCiAgKSArCiAgIyBhZGQgbWVkaWFuIGRpYW1vbmQgZm9yIGNvbmZpZGVudCBwb2ludHMgb25seQogIHN0YXRfc3VtbWFyeSgKICAgIGRhdGEgPSBkZWx0YV9tZWRpYW5fY29uZmlkZW50X2RmLAogICAgY29sb3IgPSAicmVkIiwKICAgIGdlb20gPSAicG9pbnQiLAogICAgZnVuID0gIm1lZGlhbiIsCiAgICBzaGFwZSA9IDE4LAogICAgc2l6ZSA9IDIuMjUsCiAgICBhbHBoYSA9IDAuOQogICkgKwogIGd1aWRlcygKICAgIGFscGhhID0gRkFMU0UsCiAgICBzaGFwZSA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KHNpemUgPSAxLjUsIGFscGhhID0gMC41NSkpCiAgKSArCiAgdGhlbWUoCiAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIgogICkKYGBgCgoKPCEtLS0tLS0tLS0tLS0tLS0tLS0tLS0tIENlbGxBc3NpZ24gcHJvYmFiaWxpdHkgcGxvdCAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLT4KYGBge3IsIGV2YWwgPSBoYXNfY2VsbGFzc2lnbn0Ka25pdHI6OmFzaXNfb3V0cHV0KCIKIyMgYENlbGxBc3NpZ25gIGFubm90YXRpb25zCgpUbyBhc3Nlc3MgdGhlIHF1YWxpdHkgb2YgYENlbGxBc3NpZ25gIGNlbGwgdHlwZSBhbm5vdGF0aW9ucywgd2UgY29uc2lkZXIgdGhlIHByb2JhYmlsaXR5IGFzc29jaWF0ZWQgd2l0aCB0aGUgYW5ub3RhdGVkIGNlbGwgdHlwZS4KVGhlc2UgcHJvYmFiaWxpdGllcyBhcmUgcHJvdmlkZWQgZGlyZWN0bHkgYnkgYENlbGxBc3NpZ25gOgoKLSBgQ2VsbEFzc2lnbmAgZmlyc3QgY2FsY3VsYXRlcyB0aGUgcHJvYmFiaWxpdHkgb2YgZWFjaCBjZWxsIGJlaW5nIGFubm90YXRlZCBhcyBlYWNoIGNlbGwgdHlwZSBwcmVzZW50IGluIHRoZSByZWZlcmVuY2UuCi0gYENlbGxBc3NpZ25gIHRoZW4gYW5ub3RhdGVzIGNlbGxzIGJ5IHNlbGVjdGluZyB0aGUgY2VsbCB0eXBlIHdpdGggdGhlIGhpZ2hlc3QgcHJvYmFiaWxpdHkgYW1vbmcgYWxsIGNlbGwgdHlwZXMgY29uc2lkZXJlZC4KLSBUaGVzZSBwcm9iYWJpbGl0aWVzIHJhbmdlIGZyb20gMCB0byAxLCB3aXRoIGxhcmdlciB2YWx1ZXMgaW5kaWNhdGluZyBncmVhdGVyIGNvbmZpZGVuY2UgaW4gYSBnaXZlbiBjZWxsIHR5cGUgbGFiZWwuCldlIHRoZXJlZm9yZSBleHBlY3QgcmVsaWFibGUgbGFiZWxzIHRvIGhhdmUgdmFsdWVzIGNsb3NlIHRvIDEuCgpUaGUgcGxvdCBiZWxvdyBzaG93cyB0aGUgZGlzdHJpYnV0aW9uIG9mIGBDZWxsQXNzaWduYC1jYWxjdWxhdGVkIHByb2JhYmlsaXRpZXMgZm9yIHRoZSBmaW5hbCBjZWxsIHR5cGUgbGFiZWxzLgpMaW5lIHNlZ21lbnRzIHJlcHJlc2VudCBpbmRpdmlkdWFsIHZhbHVlcyB0aGF0IGNvbXByaXNlIGVhY2ggZGlzdHJpYnV0aW9uLgoKRm9yIGNlbGwgdHlwZXMgd2l0aCAyIG9yIGZld2VyIGxhYmVsZWQgY2VsbHMsIG9ubHkgdGhlIGluZGl2aWR1YWwgdmFsdWUgbGluZSBzZWdtZW50cyBhcmUgc2hvd24uCkxpbmUgc2VnbWVudHMgYXJlIGFsc28gdGFsbGVyIGZvciBhbnkgY2VsbCB0eXBlIGxhYmVsIHdpdGggNSBvciBmZXdlciBjZWxscy4KIikKCiMgRGV0ZXJtaW5lIGhlaWdodCBpbiBpbmNoZXMgZm9yIHBsb3QgYXJlYQpwbG90X2hlaWdodCA8LSBjZWlsaW5nKGxlbmd0aCh1bmlxdWUoY2VsbHR5cGVfZGYkY2VsbGFzc2lnbl9jZWxsdHlwZV9hbm5vdGF0aW9uKSkgLyAyLjUpCmBgYAoKCmBgYHtyLCBldmFsID0gaGFzX2NlbGxhc3NpZ24sIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGZpZy5oZWlnaHQgPSBwbG90X2hlaWdodCwgZmlnLndpZHRoID0gOH0KIyBkZWZpbmUgYmFuZHdpZHRoIGZvciBhbGwgY2FsY3VsYXRpb25zCmRlbnNpdHlfYncgPC0gMC4wMwoKIyBmaW5kIHRoZSBtYXhpbXVtIGRlbnNpdHkgYWNyb3NzIGFsbCBkaXN0cmlidXRpb25zLCBhbmQKIyAgc2F2ZSB0aGUgbWF4aW11bSBmb3IgZGV0ZXJtaW5pbmcgZ2VvbV9zZWdtZW50IGhlaWdodAp5X21heCA8LSBjZWxsdHlwZV9kZiRjZWxsYXNzaWduX21heF9wcmVkaWN0aW9uIHw+CiAgc3BsaXQoY2VsbHR5cGVfZGYkY2VsbGFzc2lnbl9jZWxsdHlwZV9hbm5vdGF0aW9uKSB8PgogICMgbWFrZSBzdXJlIHdlIGdldCByaWQgb2YgYW55IHNtYWxsIGdyb3VwcwogIHB1cnJyOjpkaXNjYXJkKFwoeCkgc3VtKGlzLmZpbml0ZSh4KSkgPD0gMikgfD4KICAjIHJlbW92ZSBhbnkgTkEncyB0aGF0IG1heSBoYXZlIHNsaXBwZWQgaW4KICBwdXJycjo6bWFwX2RibCgKICAgIFwoeCkgbWF4KGRlbnNpdHkoeCwgYncgPSBkZW5zaXR5X2J3LCBuYS5ybSA9IFRSVUUpJHkpCiAgKSB8PgogIG1heChuYS5ybSA9IFRSVUUpCgojIGFkZCBjb3VudCB0byBjZWxsdHlwZV9kZiBmb3Igc2V0dGluZyBhbHBoYSBhbmQgeWVuZCB2YWx1ZXMKY2VsbHR5cGVfZGYgPC0gY2VsbHR5cGVfZGYgfD4KICBkcGx5cjo6YWRkX2NvdW50KGNlbGxhc3NpZ25fY2VsbHR5cGVfYW5ub3RhdGlvbikKCiMgbWFrZSB0aGUgcGxvdCEKZ2dwbG90KGNlbGx0eXBlX2RmKSArCiAgYWVzKHggPSBjZWxsYXNzaWduX21heF9wcmVkaWN0aW9uKSArCiAgZ2VvbV9kZW5zaXR5KAogICAgYncgPSBkZW5zaXR5X2J3LAogICAgZmlsbCA9ICJncmV5NjUiLAogICAgbGluZXdpZHRoID0gMC4yNSwKICAgIGJvdW5kcyA9IGMoMCwgMSkKICApICsKICBnZW9tX3NlZ21lbnQoCiAgICBhZXMoCiAgICAgICMgc2V0IGFscGhhIHRvIHZhcnkgYmFzZWQgb24gdGhlIG51bWJlciBvZiBwb2ludHMgaW4gdGhlIHJvdyBzdWNoIHRoYXQKICAgICAgIyAgcm93cyB3aXRoIG1vcmUgcG9pbnRzIGFyZSBtb3JlIHRyYW5zcGFyZW50CiAgICAgIGFscGhhID0gcG1heCgwLjIsIDEgLSAwLjAxICogbiksCiAgICAgIHhlbmQgPSBjZWxsYXNzaWduX21heF9wcmVkaWN0aW9uLAogICAgICAjIHNldCB5ZW5kIGFzIGVpdGhlciAwIGZvciByb3dzIHdpdGggbWFueSBwb2ludHMsIG9yIHlfbWF4LzIuNSBmb3IKICAgICAgIyAgcm93cyB3aXRoIGZldyBwb2ludHMKICAgICAgeWVuZCA9IGlmZWxzZShuID4gNSwgMCwgeV9tYXggLyAyLjUpLAogICAgICB5ID0gLUluZgogICAgKSwKICAgIGNvbG9yID0gImJsdWUiCiAgKSArCiAgbGFicygKICAgIHggPSAiUHJvYmFiaWxpdHkgb2YgYW5ub3RhdGVkIGNlbGwgdHlwZSIsCiAgICB5ID0gIkNlbGwgdHlwZSBhbm5vdGF0aW9uIgogICkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHMgPSBjKDAsIDEpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMC4xLCAwLjEpKSArCiAgc2NhbGVfYWxwaGFfaWRlbnRpdHkoKSArCiAgZmFjZXRfZ3JpZCgKICAgIHJvd3MgPSB2YXJzKGNlbGxhc3NpZ25fY2VsbHR5cGVfYW5ub3RhdGlvbiksCiAgICBzd2l0Y2ggPSAieSIKICApICsKICB0aGVtZSgKICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICBzdHJpcC50ZXh0LnkubGVmdCA9IGVsZW1lbnRfdGV4dCgKICAgICAgYW5nbGUgPSAwLAogICAgICBoanVzdCA9IDEKICAgICksCiAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwYW5lbC5zcGFjaW5nID0gdW5pdCgwLjAyLCAiaW4iKQogICkKYGBgCgoKIyBTZXNzaW9uIEluZm8KPGRldGFpbHM+CjxzdW1tYXJ5PlIgc2Vzc2lvbiBpbmZvcm1hdGlvbjwvc3VtbWFyeT4KYGBge3Igc2Vzc2lvbl9pbmZvfQppZiAocmVxdWlyZU5hbWVzcGFjZSgic2Vzc2lvbmluZm8iLCBxdWlldGx5ID0gVFJVRSkpIHsKICBzZXNzaW9uaW5mbzo6c2Vzc2lvbl9pbmZvKCkKfSBlbHNlIHsKICBzZXNzaW9uSW5mbygpCn0KYGBgCjwvZGV0YWlscz4K